Graphon Engine

Add a file

AI Draft

Add and replace files using inline text, uploads, and storage URIs.

Add content from inline text, an upload, or a supported storage URI. Track processing, replace content at the same path, and recover from failures.

Before you begin

Create a namespace and collection first. The examples use acme and incident-logs. Your key needs write within that collection. Register a webhook to receive processing status. The quickstart creates these resources.

Source

Inline

Text in JSON

Source

Upload

PUT to a signed URL

Source

URI

A readable storage object

Add a file · receive file and job IDs

Pending

Await input

Upload bytes when required.

Indexing

Prepare content

Receive status events.

Ready

Retrieve

Search and Answer can use the file.

If processing fails, read the file or job error. Correct the source before submitting a replacement.

All source types create a file and a job. An upload also requires a PUT. Wait for a ready event before relying on the file in retrieval.

Add inline text

Use inline for a small text file. path names the file inside the collection, content_type declares its media type, and text contains its UTF-8 content. metadata stores your application’s additional facts.

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

POST /namespaces/acme/collections/incident-logs/files HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>
Content-Type: application/json
Idempotency-Key: checkout-text-version-1

{
  "path": "/incidents/checkout.txt",
  "source": {
    "type": "inline",
    "content_type": "text/plain",
    "text": "Checkout stalled because the service exhausted its connection pool. Increase the pool size before the next deployment."
  },
  "metadata": {
    "environment": "production",
    "service": "checkout"
  }
}

202 Accepted

{
  "file": {
    "id": "fil_01J8Z3K4N5P6Q7R8S9T0V1W2X3",
    "path": "/incidents/checkout.txt",
    "status": "indexing",
    "stage": "engine_queued",
    "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:00:00Z"
  },
  "job": {
    "id": "job_01J8Z3K4N5P6Q7R8S9T0V1W2X3",
    "type": "index_file",
    "status": "running",
    "namespace": "acme",
    "collection": "incident-logs",
    "file_id": "fil_01J8Z3K4N5P6Q7R8S9T0V1W2X3",
    "error": null,
    "created_at": "2026-10-06T12:00:00Z",
    "updated_at": "2026-10-06T12:00:00Z"
  }
}

The response includes source.bytes, not source.text. Save file.id and job.id. The entire JSON body, including escaped text and metadata, must fit within 1,048,576 bytes.

Upload file bytes

Use upload when you have bytes rather than a URI the cluster can read. Engine returns an upload destination and expiry time. Upload the bytes before that time.

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

POST /namespaces/acme/collections/incident-logs/files HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>
Content-Type: application/json
Idempotency-Key: incident-notes-upload-1

{
  "path": "/incidents/notes.txt",
  "source": {
    "type": "upload",
    "content_type": "text/plain",
    "bytes": 15
  }
}

201 Created

{
  "file": {
    "id": "fil_01J8Z3K4N5P6Q7R8S9T0V1W2X3",
    "path": "/incidents/notes.txt",
    "status": "pending",
    "stage": null,
    "source": {
      "type": "upload",
      "content_type": "text/plain",
      "bytes": 15
    },
    "metadata": {},
    "created_at": "2026-10-06T12:00:00Z",
    "updated_at": "2026-10-06T12:00:00Z"
  },
  "job": {
    "id": "job_01J8Z3K4N5P6Q7R8S9T0V1W2X3",
    "type": "index_file",
    "status": "queued",
    "namespace": "acme",
    "collection": "incident-logs",
    "file_id": "fil_01J8Z3K4N5P6Q7R8S9T0V1W2X3",
    "error": null,
    "created_at": "2026-10-06T12:00:00Z",
    "updated_at": "2026-10-06T12:00:00Z"
  },
  "upload": {
    "url": "https://upload.example.com/signed-destination",
    "expires_at": "2026-10-06T12:15:00Z"
  }
}

Use the actual upload.url returned by Engine, including its query string. The URL authorizes the upload. It is a different destination from the Engine API.

PUT to the returned upload.url · illustrative destination

PUT /signed-destination HTTP/1.1
Host: upload.example.com
Content-Type: text/plain

Incident notes.

A successful PUT supplies the bytes. Processing then starts. If no upload arrives before upload.expires_at, the file fails. Request another upload with a new idempotency key and complete it before the new expiry.

Add from a storage URI

Call /info and check storage.schemes. For a supported URI, grant the cluster read access to the object. bytes is an optional declared size, and checksum can identify the expected source content.

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

POST /namespaces/acme/collections/incident-logs/files HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>
Content-Type: application/json
Idempotency-Key: checkout-video-version-1

{
  "path": "/incidents/checkout-video.mp4",
  "source": {
    "type": "uri",
    "uri": "gs://acme-ingest/incidents/checkout-video.mp4",
    "content_type": "video/mp4",
    "bytes": 1048576
  },
  "metadata": {
    "service": "checkout"
  }
}

The response is 202 with a file and an indexing job, as in the inline example. A later change at the storage URI does not update the indexed content. Submit another add request to index changed bytes.

FailureAction

400 invalid_uri

Check the URI syntax and schemes reported by /info.

422 storage_unreachable

Check the object exists and the cluster can read it.

409 idempotency_conflict

Use the original body for a retry, or a new key for new content.

Replace an existing file

POST the same path with the replacement source. Use a new idempotency key for the new content. Retain the new file ID and job ID returned by this add. The logical path stays the same; the replacement receives a new file ID.

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

POST /namespaces/acme/collections/incident-logs/files HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>
Content-Type: application/json
Idempotency-Key: checkout-text-version-2

{
  "path": "/incidents/checkout.txt",
  "source": {
    "type": "inline",
    "content_type": "text/plain",
    "text": "The connection pool limit was increased. Checkout recovered after the service restarted."
  },
  "metadata": {
    "environment": "production",
    "service": "checkout"
  }
}

Wait for the replacement to become ready. Ordinary replacement does not need a separate reindex request. Reusing the first request’s idempotency key with different content returns 409 idempotency_conflict.

Read and remove content

Use the file ID for a detail request, or find it by exact path:

GET https://engine.example.com/namespaces/acme/collections/incident-logs/files?path=/incidents/checkout.txt

GET /namespaces/acme/collections/incident-logs/files?path=/incidents/checkout.txt HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>

200 OK

{
  "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": null
}

Get file content returns a short-lived url and expires_at when the content is available through this API. Fetch that URL through an authorized application flow. An external source can return 409 external_source instead.

Delete file returns a cleanup job. It removes the file from the collection. It does not delete the original object in an external store. See the Add file reference for all fields and response variants.

Read Get job to recover current status after a missed event. When your file is ready, follow Search to retrieve its spans.

Was this page helpful?
View as Markdown