Skip to content

Reference

Base URL: https://chat.app.urai.dev/api/v1. Every request carries Authorization: Bearer sk-urai-....

Method and path Purpose
POST /extractions Send a file. Returns 202 and a pending record, or 200 and an earlier result for identical bytes.
GET /extractions/{id} Read one record. Carries markdown when the status is ready.
DELETE /extractions/{id} Delete the record and the stored bytes. Returns 204.

There is no list endpoint. Keep the id from the POST reply.

POST /extractions takes multipart/form-data.

Part Required Notes
The file yes The first part that has a filename. The part name does not matter. Urai reads the filename and the content type from it.

A second part with a filename fails the request. A part with no filename is ignored.

{
"id": "8f0a2c31-4d7e-4f0a-9a6e-6b0d2f8c5411",
"status": "ready",
"name": "billing-policy.pdf",
"mime_type": "application/pdf",
"size_bytes": 184320,
"page_count": 18,
"chunk_count": 96,
"markdown": "# Billing Policy 2026\n...",
"created_at": "2026-08-14T18:45:53Z",
"expires_at": "2026-08-15T18:45:53Z"
}
Field Type Notes
id string UUID. Use it to poll and to delete.
status string See the table below.
name string The filename you sent.
mime_type string The type Urai detected, which can differ from the type you declared.
size_bytes integer Size of the file you sent.
page_count integer Present for PDF and PowerPoint only.
chunk_count integer Pieces the text was split into. Reported as a shape signal. Nothing is indexed.
markdown string The extracted text. Present when status is ready.
error string Why the read failed. Present when status is failed.
created_at string RFC 3339 timestamp.
expires_at string When Urai deletes the result.

A field with no value is left out. Your code reads status first, then the field that belongs to that status.

Status Meaning
pending Accepted and queued.
processing Urai is reading the file.
ready Terminal. markdown carries the text.
failed Terminal. error says what went wrong.

Poll until the status is ready or failed. No other value is terminal.

The error shape is the one the Chat Completions API uses.

{
"error": {
"message": "No such extraction. It may have expired.",
"type": "invalid_request_error",
"code": "extraction_not_found"
}
}
Status Code Cause
400 missing_file No part of the request had a filename.
400 too_many_files More than one file in the request.
400 invalid_body Urai could not read the multipart body.
400 empty_document The file has no bytes.
401 missing_api_key No Authorization header.
401 invalid_api_key Urai does not recognise the key.
401 api_key_disabled Someone disabled the key.
401 expired_api_key The key is past its expiry.
403 product_not_enabled The key is not enabled for the extraction product.
404 extraction_not_found Unknown id, an expired result, or an id from another organization.
415 unsupported_file_type No reader handles this file type.
500 (none) Server error. Urai logs the detail and does not return it.

A file that Urai accepts and then cannot read is not an HTTP error. The request returns 202, and the record ends as failed with the reason in error.

404 gives the same answer for an expired result, another organization’s id, and an id that never existed. One caller cannot learn that another caller’s document exists.

Limit Value
Files in one request 1
Size of one file 100 MB
Retention 24 hours from created_at
Billing unit One page. Word and Markdown are counted at 3,000 characters for one page, one page at least.