Skip to content

Reference

Base URL: https://chat.app.urai.dev/api/agents/{agent_id}/v1

Method Path Purpose
POST /responses Run a turn, buffered or streamed.
GET /responses/{id} Read a stored response.
DELETE /responses/{id} Delete the response and the turn that prompted it.
POST /responses/{id}/cancel Stop a running turn.
GET /responses/{id}/input_items List the thread items before that response.
GET /models The one model this agent runs on.

The routes with an id in the path take the end-user principal as ?user=, because they carry no body.

Field Type Notes
input string or array Required. The turn, or a list of message items.
instructions string Added after the agent’s own instructions. Not stored.
stream boolean Return Server-Sent Events.
user string Your identifier for the end user. Isolates stored threads.
previous_response_id string Continue the thread that produced that response.
vars object Context for this turn. Reaches tools as meta.vars. At most 32 keys.
metadata object An alias for vars. vars wins on a shared key.
reasoning object {"effort": "..."}, where the model supports it.
attachments array File ids from POST /api/openai/v1/files.
model string Accepted and ignored. The agent’s model wins.
store boolean Accepted and ignored. Threads are always stored.
tools array Rejected with 400. Configure tools on the agent.
tool_choice string or object Rejected with 400.
text.format.type string Only text. Any other value is rejected with 400.

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

input is a string, or an array of items.

Item type Handling
message, or absent Read as a turn.
Any other value Skipped. Tools run on the server, and their calls are already in the thread.
Role Handling
user A turn in the conversation. The last one drives the run.
assistant A turn in the conversation.
system Read as an instruction for this request only. Not stored.
developer The same as system.
Any other value 400 with the code invalid_input.

content is a string, or an array of parts.

Part type Handling
input_text Read as the message text. Several text parts are joined.
output_text The same, for an assistant turn you echo back.
input_image An attachment. Set image_url to a base64 data: URL, or set file_id.
input_file An attachment. Set file_data with filename, or set file_id.
Any other value Ignored, so a client sending a new OpenAI part still works.
Header Direction Purpose
Authorization: Bearer sk-urai-... Request Required. An organization API key.
x-thread-id Response The stored thread for this exchange. Sent on every route.
x-thread-id Request Continues that thread. Send only the new message.

A thread belongs to the triple of API key, user value, and agent.

{
"id": "resp_9f2c1e40-1b7c-4c65-9a30-51a6b0f2c3d1",
"object": "response",
"created_at": 1710000000,
"status": "completed",
"error": null,
"incomplete_details": null,
"instructions": null,
"model": "anthropic/claude-haiku-4-5",
"output": [],
"parallel_tool_calls": true,
"previous_response_id": null,
"store": true,
"tool_choice": "auto",
"tools": [],
"truncation": "disabled",
"usage": { "input_tokens": 1204, "input_tokens_details": { "cached_tokens": 900 },
"output_tokens": 86, "output_tokens_details": { "reasoning_tokens": 41 },
"total_tokens": 1290 },
"user": null,
"metadata": {},
"thread_id": "0723cee0-3912-434e-8450-2c701e6f9713"
}
Field Notes
id resp_ and the UUID of the assistant message.
status in_progress, completed, failed, or cancelled.
error {"code": "...", "message": "..."} when the status is failed.
instructions Your instructions for this request. Never the agent’s own.
model The model the turn ran on, as provider/model.
output The items of the turn. See below.
store Always true.
tools Always empty. The agent’s tools are not published here.
usage The whole turn, including every tool round.
metadata The vars of the thread.
thread_id A Urai addition. The stored conversation.

tool_choice, truncation, and parallel_tool_calls are fixed. They report how the agent runs, and a request cannot change them.

Type Fields
reasoning id (rs_), summary[] of summary_text parts.
function_call id (fc_), call_id, name, arguments as a JSON string, status.
message id (msg_), role, status, content[] of output_text parts.

function_call.status is completed, incomplete when the tool returned an error, or in_progress while it runs.

An output_text part carries annotations. A source the turn used appears as a url_citation:

{
"type": "url_citation",
"url": "https://example.com/shipping",
"title": "Shipping times",
"start_index": 0,
"end_index": 118
}

The span covers the whole message. Urai records which sources a turn consulted, and not which sentence each one supports.

Prefix Names
resp_ A response, which is one assistant message.
msg_ A message output item.
fc_ A function call output item.
rs_ A reasoning output item.

previous_response_id and the {id} path segment accept the prefixed form and the bare UUID.

Event Meaning
response.created The turn started.
response.in_progress The same object again.
response.output_item.added An item opened.
response.output_item.done An item closed, restated in full.
response.reasoning_summary_text.delta More reasoning text.
response.reasoning_summary_text.done The whole reasoning summary.
response.function_call_arguments.delta The arguments of a tool call.
response.function_call_arguments.done The same arguments, complete.
response.content_part.added The text part of the message opened.
response.output_text.delta More answer text.
response.output_text.done The whole answer.
response.content_part.done The text part closed.
response.completed The turn finished. Terminal.
response.failed The turn failed. Terminal.

Every event carries type and a sequence_number that starts at 0 and counts up by one. The stream has no [DONE] frame. See Streaming for the order.

GET /models:

{
"object": "list",
"data": [{ "id": "anthropic/claude-haiku-4-5", "object": "model",
"created": 1710000000, "owned_by": "Support agent" }]
}

DELETE /responses/{id}:

{ "id": "resp_9f2c1e40-...", "object": "response", "deleted": true }

GET /responses/{id}/input_items:

{
"object": "list",
"data": [{ "id": "msg_1c9a...", "type": "message", "role": "user",
"content": [{ "type": "input_text", "text": "Where is order 4821?" }] }],
"first_id": "msg_1c9a...",
"last_id": "msg_1c9a...",
"has_more": false
}
{
"error": {
"message": "An agent brings its own tools. Configure them on the agent instead of sending them per request.",
"type": "invalid_request_error",
"param": "tools",
"code": "tools_not_supported_for_agent"
}
}
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 invalid_agent_id The agent id in the path is not a UUID.
404 agent_not_found No such agent, or it belongs to another organization or another project.
403 agent_api_disabled The API is off for this agent. Enable it on the agent’s settings page.
400 tools_not_supported_for_agent The request sent tools or tool_choice.
400 unsupported_response_format text.format.type is not text.
400 invalid_input No user message, an empty final turn, or an unknown role.
400 invalid_vars vars or metadata is not an object, or the merge holds over 32 keys.
400 invalid_response_id previous_response_id or the path id is not a UUID.
400 invalid_thread_id x-thread-id is not a UUID.
400 model_not_configured The agent has no model. Set one on the agent.
400 invalid_attachment A remote URL, a bad data URL, invalid base64, or a file part with no payload.
400 attachment_too_large One attachment is over 25 MiB.
400 too_many_attachments More than 16 attachments in one request.
404 response_not_found Unknown response, or it belongs to another key, user, or agent.
404 thread_not_found The x-thread-id thread does not belong to this key, user, and agent.
500 (none) Server error. Urai logs the detail and does not return it.
502 (none) The turn could not start, or the agent’s model is not enabled.

A turn that fails after it starts returns 200. The body carries "status": "failed" and an error with the code agent_error.

A tool that fails at run time is not an error of the request. The agent reads the failure and continues, and the tool’s output item closes with "status": "incomplete".

Limit Value
Request body 64 MiB. Base64 adds about one third to the size of the bytes.
Attachments in one request 16
Size of one attachment 25 MiB after decoding
vars and metadata keys 32 after the merge
Buffered request 10 minutes. A longer turn returns "status": "failed".
Streamed request No time limit.
Turns in flight per thread 1
input_items paging None. The list returns every item, with has_more: false.
usage scope The whole turn, including every tool round.