Overview
The Knowledge API gives you the retrieval layer on its own. You create collections, you push documents into them, and you search them. Urai returns the matching passages with a citation for each one.
Use it when your own code builds the prompt, renders a result list, or keeps a
collection in step with another system. When you want a finished answer instead,
name the search_documents tool in a
completion, and Urai does the search for you.
The API works on the same collections as the Knowledge page in the app. A document you upload in the browser is searchable here, and the reverse.
Your uraijs code reads the same documents. A tool or a workflow imports
urai:knowledge and streams the whole text of a document, at any size, without
it passing through a model. See
Read documents from code.
Base URL
Section titled “Base URL”https://chat.app.urai.dev/api/v1/knowledgeEvery path on this page is relative to that base URL.
Authenticate
Section titled “Authenticate”Send an API key as a bearer token, the same key the Chat Completions API uses.
Authorization: Bearer sk-urai-...The key sets the organization. Every collection and every document you can reach belongs to that organization, and one from another organization reads as absent.
An organization admin can limit a key to some products. A key with no product
list reaches everything, and that is what every key made in the app has. A key
that names extraction alone gets 403 and the code product_not_enabled
here, because knowledge and extraction are sold apart.
How a document becomes searchable
Section titled “How a document becomes searchable”- You create a collection, or you use one that exists.
- You push a file or a block of text into it. Urai replies with
202and the statuspending. - Urai reads the document, splits it into passages, and indexes them. Large files take tens of seconds.
- The status becomes
ready, and the passages answer searches.
Poll GET /documents/{id} until the status is ready or failed. Nothing is
searchable before that.
A first collection, end to end
Section titled “A first collection, end to end”Create the collection:
curl https://chat.app.urai.dev/api/v1/knowledge/collections \ -H "Authorization: Bearer $URAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Billing policies", "description": "Refunds, plans, invoices" }'{ "id": "9b1c8d2e-...", "slug": "billing-policies", "name": "Billing policies", "description": "Refunds, plans, invoices", "documents": { "ready": 0, "pending": 0, "failed": 0, "total": 0, "bytes": 0 }, "created_at": "2026-08-15T09:12:00Z", "updated_at": "2026-08-15T09:12:00Z"}Push a document into it:
curl https://chat.app.urai.dev/api/v1/knowledge/collections/billing-policies/documents \ -H "Authorization: Bearer $URAI_API_KEY" \ -F "file=@billing-policy-2026.pdf" \ -F "tags=policy"Search it when the status is ready:
curl https://chat.app.urai.dev/api/v1/knowledge/search \ -H "Authorization: Bearer $URAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "query": "refund window for annual plans", "collections": ["billing-policies"] }'Name a collection by its slug
Section titled “Name a collection by its slug”Every path that takes {reference} accepts the slug or the UUID. The slug comes
from the name, and a rename does not change it. Hard-code the slug in an
integration, and the same code works in every environment.
/collections/billing-policies/collections/9b1c8d2e-4a77-4c31-9f60-b1a2c3d4e5f6The collections field of a search is different. It matches the slug or the
display name, and it does not take a UUID. See
Search documents.
Every list has one shape
Section titled “Every list has one shape”GET /collections and the document lists return the same envelope.
{ "data": [], "total": 128, "limit": 50, "offset": 0 }total is what exists, and data is the page you asked for. The default limit
is 50 and the highest is 500. A limit or an offset outside the range is
corrected, not refused, and the reply tells you what was used.
Search pages differently, because the index cannot count matches honestly. It
answers has_more instead of total.
What Urai reads
Section titled “What Urai reads”| Format | Extensions |
|---|---|
.pdf |
|
| Word | .docx |
| PowerPoint | .pptx |
| Markdown and plain text | .md, .markdown, .txt, .text |
Urai reads the type from the file extension first, then from the content type.
Any other type is rejected with 415 before anything is stored.
Scanned PDF pages go through OCR. When no text can be read at all, the document
ends as failed and says so in error.
How search works
Section titled “How search works”Urai searches for keywords and for meaning at the same time, then merges the two rankings. A question that uses none of the words in the document still finds the correct passage.
Each passage carries a reference, such as p. 4 or Billing > Refunds, so
your interface can cite the source. Pages appear for PDF and PowerPoint. Word
files and Markdown files have no pages.
What it costs
Section titled “What it costs”Three meters, all visible in Usage:
| Kind | Unit | When |
|---|---|---|
knowledge_indexing |
One page | Urai reads a document into a collection. Word and Markdown are counted at 3,000 characters for one page. |
knowledge_search |
One query | Each search that reaches the index. |
knowledge_storage |
One GB-day | A daily measure of what your collections hold. The month adds up to GB-months. |
A search from the app, from the search_documents tool, and from this API are
all recorded, and each says where it came from. A document that is already in the
collection is not charged for again, and a reprocess that reuses the earlier read
is not charged for either.