Skip to content

Reference

Base URL: https://chat.app.urai.dev/api/openai/v1

Method Path Purpose
POST /chat/completions Create a completion, buffered or streamed.
GET /models List the models the key’s organization can use.
GET /models/{id} Read one model. The id contains a slash.
POST /files Upload a file. Multipart. Returns 201.
GET /files List the 100 most recent files for the key and user.
GET /files/{id} Read one file object.
GET /files/{id}/content Download the bytes.
DELETE /files/{id} Delete the file.

The /files reads and the delete take the principal as ?user=, because they carry no body.

Field Type Notes
model string Required. The form provider/model.
messages array Required. At least one user or assistant message.
temperature number Sampling temperature.
top_p number Nucleus sampling.
max_tokens integer Maximum tokens to generate.
max_completion_tokens integer The same limit. This field wins over max_tokens.
stop string or array One stop sequence, or a list of them.
seed integer Best effort, where the provider supports it.
stream boolean Return Server-Sent Events.
stream_options object {"include_usage": true} adds a final usage chunk.
tools array Tools the model can use. Only function.name is read.
tool_choice string or object "none", "auto", "required", or a function object.
response_format object text, json_object, or json_schema.
user string Your identifier for the end user. Also isolates stored threads.
metadata object Urai extension. Reaches tools as meta.vars.
knowledge object Urai extension. {"collections": [...]} limits the knowledge tools.
attachments array Urai extension. File ids, attached to the last user message.

Urai accepts any other OpenAI field and ignores it. A request built by a typed OpenAI SDK therefore works without a change.

Role Handling
system Becomes a system instruction.
developer Becomes a system instruction.
user Becomes a turn in the conversation.
assistant Becomes a turn in the conversation.
tool Ignored. Urai runs tools on the server.
Any other value 400 with the code invalid_role.

A request with no user or assistant message returns 400.

Urai does not store system messages on a thread. Send them on every request.

content is a string, or an array of parts.

Part type Handling
text Read as the message text. Several text parts are joined.
image_url An attachment. The url must be a base64 data: URL.
file An attachment. Set file_data or file_id. A part with neither fails.
Any other value Ignored, so a client sending a new OpenAI part still works.

Attachments are read on user messages only. See Send files and images.

Header Direction Purpose
Authorization: Bearer sk-urai-... Request Required. Identifies the key and its organization.
x-thread-id Response The stored thread for this exchange.
x-thread-id Request Continues that thread. Send only the new message.

A thread belongs to the pair of API key and user value. Send the same user value that created the thread.

A buffered completion:

{
"id": "chatcmpl-...",
"object": "chat.completion",
"created": 1710000000,
"model": "anthropic/claude-haiku-4-5",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "..." },
"finish_reason": "stop"
}
],
"usage": { "prompt_tokens": 36, "completion_tokens": 14, "total_tokens": 50 }
}

A streamed chunk:

{
"id": "chatcmpl-...",
"object": "chat.completion.chunk",
"created": 1710000000,
"model": "anthropic/claude-haiku-4-5",
"choices": [{ "index": 0, "delta": { "content": "..." }, "finish_reason": null }]
}

The final usage chunk, sent when stream_options.include_usage is true:

{
"id": "chatcmpl-...",
"object": "chat.completion.chunk",
"created": 1710000000,
"model": "anthropic/claude-haiku-4-5",
"choices": [],
"usage": { "prompt_tokens": 46, "completion_tokens": 21, "total_tokens": 67 }
}

The stream ends with data: [DONE].

A file object, from every /files route except the content download:

{
"id": "9d4c1f7e-...",
"object": "file",
"bytes": 184320,
"created_at": 1710000000,
"filename": "invoice-2041.pdf",
"purpose": "user_data",
"mime_type": "application/pdf"
}

mime_type is a Urai addition to OpenAI’s shape. purpose defaults to user_data and is returned as you sent it. DELETE /files/{id} returns {"id": "...", "object": "file", "deleted": true}.

Value Meaning
stop The model finished the answer.
length The token limit cut the output.
content_filter The provider’s safety filter stopped the output.
tool_calls The provider stopped on a tool call.
Name Purpose
web_search Search the web. See the provider table.
web_fetch Read the full text of web pages. Not on Gemini, where urlContext does this.
search_documents Search the organization’s knowledge collections.
read_document Read one document from those collections in full.

Any other name in tools[] must match a UraiJS tool in your organization.

{
"error": {
"message": "The model 'openai/gpt-4o' is not available for this organization",
"type": "invalid_request_error",
"param": "model",
"code": "model_not_found"
}
}
Status Code Cause
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.
400 model_not_found Unknown model, or no credential for it in this organization.
400 invalid_role A message has an unknown role.
400 invalid_tool_choice tool_choice has a bad value or shape.
400 unknown_tool A name in tools[] matches no built-in and no tool in the organization.
400 tools_unavailable UraiJS is not available for this organization.
400 tool_not_configured The tool needs a credential or a collection that is missing.
400 unknown_collection knowledge.collections names a collection that does not exist.
400 invalid_response_format Bad schema name or shape, or response_format sent with tool_choice: "required".
400 invalid_thread_id x-thread-id is not a UUID.
400 invalid_attachment A remote URL, a bad data URL, invalid base64, or a file part with neither file_data nor file_id.
400 attachment_too_large One attachment is over 25 MiB.
400 too_many_attachments More than 16 attachments in one request.
400 invalid_multipart POST /files could not read the multipart body.
400 missing_file POST /files had no file part.
400 invalid_file The uploaded file is empty.
400 (none) messages holds no user or assistant message.
404 thread_not_found The thread does not belong to this key and user.
404 file_not_found Unknown file id, or the id belongs to another user.
404 model_not_found GET /models/{id} found no such model.
500 (none) Server error. Urai logs the detail and does not return it.
502 (none) The model provider returned an error.

A tool that fails at run time does not produce an HTTP error. The model receives the error, and the request returns 200 with the model’s report of the problem.

Limit Value
Choices per response 1. The endpoint does not support n greater than 1.
Attachments in one request 16
Size of one attachment 25 MiB after decoding
Completion request body 64 MiB. Base64 adds about one third to the size of the bytes.
Files returned by GET /files The 100 most recent
Tool rounds per request 10. The turn then stops with finish_reason: "stop".
Passages per search_documents call 8 by default, 25 at most.
read_document window About 40,000 characters. The reply carries next_seq for the rest.
usage scope The whole request, including every tool round.