Graphon Engine

Filter and paginate results

AI Draft

Select data, order Search pages, and use continuation cursors.

Select the right files, order a page of Search results, and continue through responses with cursors. Filters narrow data; access rules authorize readers.

Build a filter

Search, Answer, and Research accept a filter object. A leaf clause has field, op, and value. Combine clauses with and, or, or not. The filter below selects production incident files. It needs environment in the collection’s metadata fields.

PATCH https://engine.example.com/namespaces/acme/collections/incident-logs/metadata-fields

PATCH /namespaces/acme/collections/incident-logs/metadata-fields HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>
Content-Type: application/json

{
  "fields": {
    "environment": {
      "type": "text"
    }
  }
}

A filter can read a metadata key only when the collection lists it, with a type: text, number, time, or bool. A new collection lists no key. A change returns 202 with a reindex_metadata job. On a collection with files, the index is rebuilt in the background, and the job stays running until the rebuild is done. Filters read the old index until the job succeeds. See Update metadata fields.

POST https://engine.example.com/namespaces/acme/collections/incident-logs:search

POST /namespaces/acme/collections/incident-logs:search HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>
Content-Type: application/json

{
  "query": "checkout",
  "mode": "keyword",
  "filter": {
    "and": [
      {
        "field": "path",
        "op": "prefix",
        "value": "/incidents/"
      },
      {
        "field": "metadata.environment",
        "op": "eq",
        "value": "production"
      }
    ]
  },
  "limit": 10
}
Field or operatorMeaning

Built-in fields

path, content_type, bytes, created_at, updated_at, and status.

Metadata fields

Use metadata.{key}, such as metadata.environment. The key must be a listed metadata field. Its type sets the operators. text takes all of them. number takes eq, neq, gt, gte, lt, lte, and in. time takes eq, neq, gt, gte, lt, and lte. bool takes eq, neq, and in.

eq, neq

Equal or unequal to one value.

gt, gte, lt, lte

Ordered comparisons with a compatible value type.

prefix

A string begins with the supplied prefix.

in

The field matches a value in the supplied array.

and, or, not

Combine clauses or negate one clause.

Use values that match the field: numeric byte counts, UTC timestamp strings, and text for paths or media types. A metadata value is read by its field type, so a number field takes 10 or "10". Unsupported fields, operators, or value combinations return 400 invalid_filter. Its details can name the field or operator. For a metadata key that is not listed, details.reason is not_listed.

Paginate resource lists

Resource lists use query parameters limit and cursor. They return items and next_cursor. The default page size is 50 and the maximum is 100.

GET https://engine.example.com/namespaces/acme/collections/incident-logs/files?prefix=/incidents/&limit=1

GET /namespaces/acme/collections/incident-logs/files?prefix=/incidents/&limit=1 HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>

200 OK · illustrative continuation token

{
  "items": [
    {
      "id": "fil_01J8Z3K4N5P6Q7R8S9T0V1W2X3",
      "path": "/incidents/checkout.txt",
      "status": "ready",
      "stage": null,
      "source": {
        "type": "inline",
        "content_type": "text/plain",
        "bytes": 118
      },
      "metadata": {
        "environment": "production",
        "service": "checkout"
      },
      "created_at": "2026-10-06T12:00:00Z",
      "updated_at": "2026-10-06T12:01:00Z"
    }
  ],
  "next_cursor": "<NEXT_CURSOR>"
}

URL-encode the actual returned cursor and send it with the same list parameters. Do not use the illustrative token below. Continue until next_cursor is null.

GET https://engine.example.com/namespaces/acme/collections/incident-logs/files?prefix=/incidents/&limit=1&cursor=<URL_ENCODED_NEXT_CURSOR>

GET /namespaces/acme/collections/incident-logs/files?prefix=/incidents/&limit=1&cursor=<URL_ENCODED_NEXT_CURSOR> HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>

List cursors expire after one hour. A cursor belongs to its original request and key. An expired or mismatched cursor returns 400 invalid_cursor; restart from the first page.

Search returns results and its own next_cursor. Send the returned cursor in the next JSON body. Keep the query, mode, interpretation, filter, principals, result type, and limit unchanged.

POST https://engine.example.com/namespaces/acme/collections/incident-logs:search

POST /namespaces/acme/collections/incident-logs:search HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>
Content-Type: application/json

{
  "query": "checkout",
  "mode": "hybrid",
  "limit": 10,
  "cursor": "<NEXT_CURSOR>"
}

Search cursors last 40 minutes and preserve the search’s index generation. Treat every cursor as opaque. Do not share cursors across keys or reuse them for a different search.

The default file result type returns a file on one page only. next_cursor: null ends traversal. A fresh first-page request can include newly indexed content. See Pagination and idempotency for the complete conventions.

Keep access separate

Filters select data

A caller can omit a filter. Use enforced access rules and trusted principals for per-reader authorization. Apply those rules before content reaches a Search result or an answer.

See Apply access rules for a complete example.

Was this page helpful?
View as Markdown