Skip to main content
RAG lets you upload files, automatically convert them into searchable chunks, and then query them with plain-language questions. The API returns the most relevant passages, which you can feed directly into a chat completion to get answers grounded in your own content. The full flow is three steps:
  1. Upload a file and get a file_id
  2. Wait for embeddings to finish processing
  3. Search with a natural-language query

Step 1 — Upload a file

Call POST /v1/files to register the file. You get back a file_id and a short-lived signed_url — use the signed URL to PUT the actual bytes directly to storage.

Init upload fields

Init upload response

The signed_url expires 15 minutes after you get it. PUT the bytes right away, and send every header in required_headers exactly as given: they are part of the signature, and a missing or changed one makes storage reject the upload. Files are capped at max_size_bytes (50 MB).
File ids are UUIDs. RAG needs a key created in the dashboard: a key whose owner isn’t a user (for example one minted with an admin key) gets 400 on upload.

Step 2 — Wait for embeddings

After the PUT completes, the API automatically chunks and embeds your file (because embed: true). You can poll GET /v1/files/{file_id} to watch progress. Give the loop a deadline: if the PUT never lands, upload_status stays pending forever.

Status fields

Once embedding_status is ready, the file is ready to search. upload_status goes to failed when the uploaded file is over 50 MB or its Content-Type doesn’t match the mime_type you registered. Register the file again. The status object also carries file_name, file_type, mime_type, size_bytes, created_at, updated_at, total_tokens, total_cost_usd and last_error_code.

Step 3 — Search your files

Send a natural-language query to POST /v1/files/search. The API embeds your query, runs a hybrid search (dense vectors plus keyword matching, merged by reciprocal rank fusion), and returns the raw text with relevance scores. The query embedding is billed to your account like any embedding call.

Search fields

Search response


End-to-end: RAG chat

Combine search results with a chat completion to answer questions from your documents.

Filtering by metadata

Tag files at upload time and filter at search time — useful when you have documents from different departments, clients, or time periods.

Re-triggering embeddings

If embed was set to false at upload time, or if embedding failed, you can kick it off manually:
The call returns 202 with a per-file status:
You can pass "wait": true to block until all embeddings finish (useful for small files in scripts). Rules, per file:
  • file_ids takes 1 to 100 ids.
  • The file’s upload_status must be ready.
  • A file that is already embedded comes back as completed; one still queued or processing comes back as processing.
  • After a failed embedding, the same file can’t be re-queued for 30 minutes. The entry comes back with embedding_status: "error" and an error saying when to retry.

List your files

Response includes files (array of file status objects), total, limit, and offset.

Delete a file

Call DELETE /v1/files/{file_id} to remove a file. Its chunks are dropped from the search index and the stored file is deleted, so the document stops appearing in POST /v1/files/search results.
A successful delete returns 204 No Content with an empty body — there is no JSON response to parse. Deleting is idempotent, so retrying is always safe and converges on a full delete. Treat a file as deleted only once you have received a 204 — if a call fails, repeat it until it succeeds rather than assuming it partly applied.
Deletion is permanent. The file’s chunks cannot be recovered, and searching it again means re-uploading and re-embedding the document from scratch.
Usage records that reference the file stay available afterwards, so your billing history and usage queries remain complete.

Common errors


File management

Supported file types