Every endpoint, generated from the same OpenAPI description the API publishes at /openapi.json, so it cannot list an endpoint the API lacks or miss one it has. Load that file into Postman, Insomnia or any OpenAPI code generator to build a client.
Earlier names
The product was first called AgentsRouter, and its own names carried it. They still work and always will: requests may send X-AgentsRouter-Agent or X-AgentRouter-Metadata instead of X-Autonomous-Relay-Agent and X-Autonomous-Relay-Metadata, and declare a server tool as agentrouter:datetime instead of autonomousrelay:datetime. Responses and webhooks carry every x-autonomous-relay-* header under its x-agentsrouter-* name as well, with the same value, so a receiver checking x-agentsrouter-signature keeps working unchanged.
265 endpoints in 30 groups.
Inference
Model requests.
Create a chat completion
OpenAI-compatible. Routes to an endpoint your guardrails and preferences allow, dispatches on your own provider credential, and fails over to the next candidate before the first byte ships -- walking models[] to exhaustion.
Free models without a key. A free model (GET /v1/models?free=true: every price zero) can be used before you add any provider key: where the platform holds a free-model key for its provider, an organisation with no key of its own for that model is served on it, at $0, with no hold. At most 50 such requests per organisation per UTC day (the operator may set another figure), across every free model and key; past that the attempt is not sent and the request is a 429 with metadata.reason: free_model_daily_limit. Your own key has no such limit, and once you add one for the provider it is used instead. The provider's own free-tier limits still apply, and its errors pass through. Every model with a price is served on your own key only.
With stream: true the response is server-sent events: one data: line per ChatCompletionChunk, SSE comments (lines starting with :) as keepalives, a final chunk carrying usage, then data: [DONE].
Authentication
Inference key (ar-v1-…) · Dashboard session
Parameters
- X-Autonomous-Relay-Metadata enum · header
enabledaddsagentrouter_metadata: on the final chunk when streaming, and besideerroron an error once routing has begun.X-Metadatais accepted too.- X-Session-Id string · header
A sticky-routing key, used when the body has no
session_id. The legacyX-AgentRouter-Metadatais accepted too.- X-Anthropic-Beta string · header
Forwarded to Anthropic as
anthropic-beta.- HTTP-Referer string · header
Your app's URL, for attribution. The app listing keeps its path; each request row keeps only the scheme and host.
- X-Autonomous-Relay-Agent string · header
The agent this request is for: 1 to 64 letters, digits,
.,_,:or-, starting with a letter or digit. Recorded on the request, and bound by that agent's budgets (PUT /v1/agents/{agent}/budgets/{interval}) across every key it uses. A malformed value is a 400 before anything is spent. The legacy nameX-AgentsRouter-Agentis accepted too.- X-Title string · header
Your app's name.
X-App-TitleandX-OpenRouter-Titleare accepted too.- X-App-Visibility enum · header
hiddenkeeps the app out of public listings. Read on the app's first request only.- X-App-Categories string · header
Up to two comma-separated categories.
- X-Cache enum · header
bypassanswers from the provider and stores nothing, on a key with the response cache on.
Request body
- model string
A catalog id,
author/slug, optionally with a variant (:free,:nitro,:floor,:exacto), or a~author/familyalias, which resolves to theauthor/family-latestrow when the catalog publishes one and otherwise resolves to nothing -- it never picks a model for you by guessing at the name. An id listed in/v1/modelsalways means that listing: some free tiers are catalog rows of their own, namedauthor/slug:free, and a suffix is only split off the id when no such row can serve the request. It always applies as a variant either way. Or@preset/<slug>(@<version>to pin one): your organisation's preset, whose settings fill in whatever this request does not set.- models string[]
A fallback chain, tried in order. At most three are attempted.
- messages ChatMessage[]
- prompt string
Legacy: sent as a single user message when
messagesis absent.- stream boolean
- Default: false
- max_tokens integer
- max_completion_tokens integer
- temperature number
- top_p number
- top_k integer
- stop string | string[]
- seed integer
- tools object[]
Client functions, and server tools the gateway runs itself:
{"type": "autonomousrelay:datetime", "parameters": {"timezone": "America/Toronto"}},{"type": "autonomousrelay:experimental__search_models"}, or a registered MCP server's tools:{"type": "autonomousrelay:mcp", "server": "<name>", "allowed_tools": [...]}(§17.7; see POST /v1/mcp-servers), offered to the model asmcp__<server>__<tool>and called by the gateway on the server's credential. An installed marketplace plugin's tools:{"type": "autonomousrelay:plugin", "plugin": "<slug>", "allowed_tools": [...]}(see POST /v1/plugins/{id}/install), offered asplugin__<slug>__<tool>and called on the install's own credential --{"type": "autonomousrelay:plugin", "plugin": "notion"}offersplugin__notion__search_pagesandplugin__notion__read_page; a plugin not installed is a 404, one turned off a 403, one that cannot list its tools a 502. Every connection at once:{"type": "autonomousrelay:connected", "include": [...], "exclude": [...], "writes": [...]}offers the READ tools of every installed plugin and MCP server (at most 10 connections and 128 functions per request), plus only the write tools named exactly inwrites-- which need arun_idwhose agent has an approval policy, and always wait for a person. A connection that does not work (not connected, expired, turned off, unreachable) is skipped, not an error: the answer comes from the rest, theX-Autonomous-Relay-Connected-Toolsresponse header andagentrouter_metadata.connected_toolssay what was used and skipped, and the organisation's alert channels (or its owners, by email) are told once a day per connection. GET /v1/tools/available shows what it would draw on. With"stream": truethe loop still runs: its progress arrives as SSE comment lines (: autonomousrelay {"type": "tool.called", ...}, which SDKs ignore), then the answer as ordinary chunks. Their use is reported inusage.server_tool_use. See GET /v1/tools for the catalogue and which are available.- max_tool_calls integer
The most server-tool executions this request may make.
Default: 30- tool_context object
Context for connector tools: a plugin tool whose connector manifest declares a key receives that key's value as
_context. A hosted agent's run started by a connector event sets it from the event. Never sent to the model provider.- tool_choice any
none,auto,required, or{"type": "function", "function": {"name": …}}.- service_tier enum
OpenAI's processing tier.
flex(Batch rates; OpenAI may refuse it with a 429 when busy, uncharged) andpriority/fast(Fast mode, a per-token premium) are sent only to an OpenAI endpoint with a published price for that tier; anywhere else the request is served at standard. Billing follows the tier the provider reports serving at -- a Fast request OpenAI serves at default is billed at default.auto,defaultandscaleare accepted and not forwarded.One of: auto, default, flex, priority, fast, scale- response_format object
{"type": "json_object"}or{"type": "json_schema", "json_schema": {"name", "schema", "strict"}}. Passed as is on OpenAI-protocol providers; on Gemini it becomes JSON mode with the schema; on Anthropic ajson_schemabecomes structured outputs, with the bounds Anthropic does not enforce (minimum,maxLength,maxItems, …) left unchecked andadditionalProperties: falseassumed where unset. A schema Anthropic cannot express (additionalPropertiesother than false, a recursive or external$ref) is sent there without a format;json_objecthas no Anthropic counterpart. Theresponse-healingplugin repairs a reply that is still not JSON.- plugins object[]
[{"id": "response-healing"}]repairs a reply that should have been JSON (response_formatjson_objectorjson_schema): markdown fences, surrounding text, trailing commas, comments, bare keys, unclosed brackets. The repair is used only if it parses; a reply that already is JSON, or thatmax_tokenscut short (finish_reason: "length"), is returned as written. Not on streams. When it changed the answer,agentrouter_metadata.pipelineincludesresponse_healing.{"id": "context-compression"}fits a conversation to the serving endpoint's context window by removing whole messages from the middle out: system and developer messages, the first message and the last always stay, and a tool call goes with its results. The window left for the prompt is the context lessmax_tokens(a quarter of the window when unset). On by default for endpoints of 8,192 tokens or less;{"id": "context-compression", "enabled": false}turns it off. With it on, Anthropic's 1,000-message limit is met the same way. Never applied to an image-output model. A failover to a larger endpoint sends the conversation whole. When it removed messages,pipelineincludescontext_compression.{"id": "file-parser", "pdf": {"engine": "pdf-text" | "native"}}decides how a PDFfilepart (file_dataas a base64 data URL, or afile_id) reaches the model.nativesends the file;pdf-textsends its text layer, read on our side, as a text part headed by the filename, page by page (at most 200 pages and 1,000,000 characters per request). Unset, each endpoint decides: the file where the model reads files, its text everywhere else, so PDFs work on any model.mistral-ocris refused: OCR would send the document to a third party, so a scanned PDF has no text here and should go to a model that reads PDFs. A file that is not a PDF, or is password-protected, is a 400 when an endpoint needs its text. When the model was given text, the answer carries it asmessage.annotations(on a stream, on the final chunk'sdelta.annotations)[{"type": "file", "file": {"hash", "name", "content": [{"type": "text", "text"}]}}]; send that assistant message back with the conversation and the annotation is used instead of reading the file again.pipelineincludesfile_parser. Nothing is stored.{"id": "auto-router", "cost_tier": "low" | "medium" | "high" | "xhigh" | "max", "allowed_models": [...], "excluded_models": [...]}configures"model": "autonomousrelay/auto": a paid model you can route to that fits the request (text out, image input when an image is sent, a window that holds it), from the tier by output price per million tokens (low to $2, the default; medium to $10; high to $30; xhigh to $60; max above), the most expensive first, then the newest; two fallbacks from the same tier; the nearest cheaper tier when the one asked for has nothing, then the nearest dearer one. Patterns take*for any run of characters. The prompt is not read and nothing is kept, so the same request picks the same model.{"id": "moderation", "input": true, "output": false}checks the input (default) and, withoutput: true, the answer, using OpenAI'somni-moderation-lateston the organisation's own OpenAI BYOK key (a 400 without one). The input is checked before any provider sees it and before anything is held; a flag is a 403 witherror_typemoderation_flaggedand metadata{reasons, flagged_input, provider_name, model_slug}. A flagged answer is withheld, and the request is billed because the model ran. Output moderation is refused on streams. If moderation cannot run, the request is refused (503), never sent unchecked.pipelineincludesmoderation.{"id": "web", "engine": "native", "max_uses": 3, "allowed_domains": [...] | "excluded_domains": [...]}lets the model search the web with its provider's own search: Anthropic's web search tool on Claude models, Google Search grounding on Gemini 3 models, and OpenAI's and xAI'sweb_searchtool (the request is run on their Responses API) on GPT-5 and later and Grok 4 models. Gemini 2.5 is not served: it is priced per grounded prompt. Only those endpoints are candidates; with none, a 404.max_uses(1-20) applies on Claude; the domain lists on Claude, OpenAI and xAI (at most 5 on xAI), so a request with domains never goes to Gemini. Each search is metered as aweb_searchline at the provider's published price per 1,000: $10 Anthropic, $14 Gemini (before Google's free monthly allowance), $10 OpenAI, $5 xAI. The pages the search cited come back asurl_citationannotations on the message (on a stream, indelta.annotationsas they arrive), withstart_index/end_indexwhere the provider gives character offsets. Outside engines (Exa and the like) are refused: they would be a new recipient of your queries. Other plugin ids are ignored.- reasoning object
{ effort: minimal|low|medium|high|xhigh|max }or{ max_tokens: n }. On Anthropic's current models (Fable, Opus 4.6 and later, Sonnet 4.6 and later) this becomes adaptive thinking witheffortas the depth (minimalislow;xhighishighon the 4.6 models); amax_tokensbudget turns thinking on at the model's default depth, since those models size their thinking inside the request's ownmax_tokens. On older Claude models it is extended thinking with that budget (floor 1024). Either way the thinking text is returned asmessage.reasoning(ordelta.reasoningwhen streaming).temperature,top_pandtop_kare dropped alongside thinking, and on Fable, Opus 4.7 and later and Sonnet 5 always, because Anthropic refuses them there.- provider ProviderPreferences
Routing preferences (§6.2). Preferences reorder; constraints reject. Guardrails outrank everything here.
- session_id string
Keeps a conversation on one endpoint so its prompt cache stays warm (§6.6).
- prompt_cache_key string
Used as the sticky-routing key when there is no
session_id.- routing_stability enum
Defaults to
stickywhen the request has a pin key,adaptiveotherwise (§17.2).One of: adaptive, sticky, pinned
Responses
- id stringrequired
gen-…. Pass it toGET /v1/generationfor the full record.- object anyrequired
- created integerrequired
Unix seconds.
- model stringrequired
The model that served, which differs from the one requested when a fallback fired.
- provider string
- choices object[]required
- usage Usagerequired
- agentrouter_metadata RouterMetadata
Why this model, this provider, this price (§7.5). Present only when
X-Autonomous-Relay-Metadata: enabledwas sent.
Create a message (Anthropic's Messages API)
Anthropic-compatible: the Anthropic SDKs work with their base URL set to this host. The request is translated to a chat completion and served by the same pipeline, so every gate, routing rule, preset, server tool and file applies, and any model answers it, not only Claude. The answer comes back as a message, or with stream: true as Anthropic's events (message_start, content_block_*, message_delta, message_stop, ping).
The key goes in x-api-key (as the Anthropic SDK sends it) or Authorization: Bearer. anthropic-version is accepted and ignored; anthropic-beta is forwarded to Anthropic. A Claude name such as claude-opus-4-8 or claude-opus-4-8-20260101 means anthropic/claude-opus-4.8; any other model is named by its catalogue id. models (or fallbacks: [{"model": ...}], at most three), provider, session_id and run_id work as on chat completions.
Not taken: Anthropic's own server tools (declare autonomousrelay:* tools instead -- autonomousrelay:plugin, autonomousrelay:mcp and autonomousrelay:connected included, as on chat completions), images inside a tool_result, a document by URL, and cache_control (ignored). Thinking blocks sent back are dropped; tool-use arguments stream as one input_json_delta per call, once the model has finished.
Authentication
Inference key (ar-v1-…) · Dashboard session
Parameters
- x-api-key string · header
An inference key, as the Anthropic SDK sends it. Used when there is no
Authorizationheader.- anthropic-version string · header
Accepted and ignored.
- anthropic-beta string · header
Forwarded to Anthropic.
- X-Autonomous-Relay-Agent string · header
The agent this request is for, as on chat completions.
Request body
- model stringrequired
A catalogue id, or a Claude name (
claude-opus-4-8).- max_tokens integerrequired
- messages object[]required
- system string | object[]
- stream boolean
- temperature number
- top_p number
- top_k integer
- stop_sequences string[]
- tools object[]
- tool_choice object
- thinking object
- metadata object
- fallbacks object[]
Models tried in order after
model.
Responses
- id string
The request id;
GET /v1/generation?id=reads it.- type enum
- One of: message
- role enum
- One of: assistant
- model string
The model that served.
- content object[]
- stop_reason enum
- One of: end_turn, max_tokens, stop_sequence, tool_use, pause_turn, refusal
- stop_sequence string | null
- usage object
Create a response (OpenAI's Responses API)
OpenAI-compatible Responses API. The request is translated to a chat completion and served by the same pipeline, so every gate, routing rule, preset, server tool and file applies, and any model answers it. The answer is a response; with stream: true, the Responses events (response.created, response.output_item.*, response.output_text.delta, response.function_call_arguments.*, response.completed or response.incomplete), each with a sequence_number.
Stateless. Nothing is stored, so store: true, previous_response_id, conversation and background are refused with a 400 rather than ignored; send the whole conversation as input. store: false is accepted.
Input items: messages (input_text, input_image by URL or file_id, input_file by file_data or file_id), function_call and function_call_output; reasoning items are dropped. Tools: function, and our autonomousrelay:* declarations -- server tools, autonomousrelay:plugin, autonomousrelay:mcp and autonomousrelay:connected, as on chat completions; OpenAI's built-in tools are refused. text.format (json_schema, json_object), reasoning.effort, max_output_tokens, tool_choice and parallel_tool_calls map to their chat equivalents; models and provider work as on chat completions. Function-call arguments stream as one delta per call, once the model has finished.
Authentication
Inference key (ar-v1-…) · Dashboard session
Parameters
- X-Autonomous-Relay-Agent string · header
The agent this request is for, as on chat completions.
Request body
- model string
A catalogue id.
- input string | object[]required
- instructions string
Sent as a system message ahead of the input.
- max_output_tokens integer
- stream boolean
- temperature number
- top_p number
- user string
- tools object[]
- tool_choice enum | object
- parallel_tool_calls boolean
- text object
- reasoning object
- store boolean
Only
false(or absent): nothing is stored.- models string[]
- provider object
Routing preferences, as on chat completions.
Responses
- id string
The request id;
GET /v1/generation?id=reads it.- object enum
- One of: response
- created_at integer
- status enum
- One of: completed, incomplete
- incomplete_details object | null
- model string
The model that served.
- output object[]
- usage object
Create a text completion (legacy)
OpenAI's legacy text completion, for clients that still call it. The prompt is sent as one user message and served by the chat pipeline -- every gate, routing rule and preset applies -- and the answer's text comes back as choices[0].text; with stream: true, as text_completion chunks ending in data: [DONE].
One prompt per request: a list of more than one is refused, since each would be its own routed and billed request. The catalogue's models are chat models, so what only a true completion model can honour is refused rather than dropped: suffix, echo, best_of and n above 1, logprobs (chat completions return them), and token-id prompts.
Authentication
Inference key (ar-v1-…) · Dashboard session
Parameters
- X-Autonomous-Relay-Agent string · header
The agent this request is for, as on chat completions.
Request body
- model string
A catalogue id.
- prompt string | string[]required
- max_tokens integer
- stream boolean
- temperature number
- top_p number
- stop string | string[]
- seed integer
- frequency_penalty number
- presence_penalty number
- user string
- models string[]
- provider object
Routing preferences, as on chat completions.
Responses
- id string
The request id;
GET /v1/generation?id=reads it.- object enum
- One of: text_completion
- created integer
- model string
The model that served.
- choices object[]
- usage object
As on chat completions.
Create embeddings
OpenAI-compatible. Routed like a chat completion -- model, an optional models[] fallback list and provider preferences -- through the same gates in the same order: auth, rate limit, every budget, the content filters (a redacted input is what is embedded), your guardrails and privacy policy, a hold, and failover before anything is returned. Billed on the provider's prompt-token count.
Only models whose catalogue modality outputs embeddings are candidates; naming a chat model is a 400 saying so. input is a string or up to 2,048 strings; token arrays are refused, since the router cannot know which tokeniser the endpoint it picks will read them with.
Authentication
Inference key (ar-v1-…) · Dashboard session
Parameters
- X-Autonomous-Relay-Agent string · header
The agent this request is for; bound by that agent's budgets, as on chat completions.
- HTTP-Referer string · header
Your app's URL, for attribution.
- X-Title string · header
Your app's name.
Request body
- model string
An embedding model id from
/v1/models.- models string[]
Fallbacks, tried in order after
model.- input string | string[]required
- encoding_format enum
base64returns each vector as little-endian float32s, base64-encoded.One of: float, base64- dimensions integer
For models that can shorten their output; others refuse it upstream.
- provider object
Routing preferences, as on chat completions.
Responses
- object enum
- One of: embedding
- index integer
- embedding number[] | string
Text to speech
OpenAI's request; the answer is the audio itself, in response_format (mp3 by default). Routed like embeddings -- model, models and provider as on chat completions, the same budgets, content filters (a redacted input is what is spoken) and guardrails. Only text-to-speech models with a published price are candidates, and the request is billed per character of input, at that price. voice is passed as given: each model has its own voices (af_bella on Kokoro, Ashley on Inworld, a free-text description on the VoiceDesign models), and its default when omitted.
The body is audio, so the request id travels in the x-autonomous-relay-generation-id header; GET /v1/generation?id= reads its cost.
Authentication
Inference key (ar-v1-…) · Dashboard session
Parameters
- X-Autonomous-Relay-Agent string · header
The agent this request is for, as on chat completions.
Request body
- model string
A text-to-speech model id from
/v1/models.- models string[]
Fallbacks, tried in order after
model.- input stringrequired
- voice string
The model's own voice name or, on a VoiceDesign model, a description.
- response_format enum
- One of: mp3, opus, flac, wav, pcm
- speed number
- provider object
Routing preferences, as on chat completions.
Responses
Speech to text
OpenAI's multipart request: file (flac, mp3, mp4, mpeg, mpga, m4a, ogg, opus, wav or webm, at most 25 MB) and model, with optional language (ISO-639-1), prompt and temperature. Routed like embeddings, through the same budgets and guardrails; the content filters read prompt. Only speech-to-text models with a published price are candidates, and the request is billed per second of audio, as the provider measured it.
response_format: json ({text, usage}), verbose_json (adds language, duration, segments, words), or text (the transcript as plain text). usage is {type: "duration", seconds, cost, ...}. The request id is also in the x-autonomous-relay-generation-id header.
Authentication
Inference key (ar-v1-…) · Dashboard session
Parameters
- X-Autonomous-Relay-Agent string · header
The agent this request is for, as on chat completions.
Responses
- text string
- usage object
Generate images
OpenAI's request and response, routed like embeddings: model, models and provider as on chat completions, through the same budgets, content filters (a redacted prompt is what is drawn) and guardrails. Only text-to-image models with a published output price are candidates; a model whose price cannot be computed from the request (per token, tiered by megapixel) is not served, and the 404 names published_price.
Billed at that price, per image or per megapixel of size ((width/1024) x (height/1024)), for the images actually returned; GET /v1/models/{author}/{slug}/endpoints shows each endpoint's image_output price and its image_output_unit. Images come back as b64_json only: nothing is hosted, so there is no URL to give. Up to 4 images; each side of size from 256 to 2048 (models may accept less).
Authentication
Inference key (ar-v1-…) · Dashboard session
Parameters
- X-Autonomous-Relay-Agent string · header
The agent this request is for, as on chat completions.
Request body
- model string
A text-to-image model id from
/v1/models.- models string[]
Fallbacks, tried in order after
model.- prompt stringrequired
- n integer
- size string
WIDTHxHEIGHTorauto(1024x1024).- response_format enum
- One of: b64_json
- provider object
Routing preferences, as on chat completions.
Responses
- b64_json string
- revised_prompt string
Rerank documents against a query
Each document's relevance to the query, most relevant first -- the request and response shape Cohere and Jina share. Routed and billed like embeddings: model, models and provider as on chat completions, the same budgets, content filters (a redacted query or document is what is scored) and guardrails, and the provider's input-token count as the bill. Only reranker models are candidates; another kind is a 400 that says so.
Served today by DeepInfra's Qwen3 rerankers. Up to 1,000 documents, each a string or {"text": ...}. instruction steers the task on models that take one.
Authentication
Inference key (ar-v1-…) · Dashboard session
Parameters
- X-Autonomous-Relay-Agent string · header
The agent this request is for, as on chat completions.
Request body
- model string
A reranker model id from
/v1/models.- models string[]
Fallbacks, tried in order after
model.- query stringrequired
- documents string | object[]required
- top_n integer
How many results to return; all by default.
- return_documents boolean
Include each result's text.
- instruction string
Steers the reranking task, on models that take one.
- provider object
Routing preferences, as on chat completions.
Responses
- id string
The request id;
GET /v1/generation?id=reads it.- object enum
- One of: list
- model string
The model that served.
- provider string
The provider that served.
- results object[]
- usage object
Preview how a request would route
Answers "why would I get that model, from that provider?" before the money is spent. Router metadata answers it afterwards; this runs the same gates, the same filters and the same ranking against a request that is never dispatched.
It mirrors POST /v1/chat/completions gate for gate and in order: the same auth, the same budget checks in the same precedence, the same content filter applied before routing, the same per-model candidate load, filter and rank, the same fallback depth, and the same sticky hoist.
It has no side effects. No ledger hold, no run reservation, no request row, no sticky pin written, no provider contacted. Rate limited in its own bucket, so debugging a routing problem never eats the quota needed to fix it.
Read ordering before trusting cascade as a prediction: the default ranking is a weighted random draw, and sampled means a real request draws again.
Authentication
Inference key (ar-v1-…) · Dashboard session
Parameters
- X-Session-Id string · header
A sticky-routing key, used when the body has no
session_id.
Request body
- model string
The model to route, exactly as
/v1/chat/completionstakes it --:free,:nitro,:floor,:exactosuffixes and~author/family-latestaliases included.- models string[]
A fallback chain, previewed in order. Walked to the same depth a real request would walk it.
- provider ProviderPreferences
Routing preferences (§6.2). Preferences reorder; constraints reject. Guardrails outrank everything here.
- tools object[]
Only the COUNT matters here: a non-empty list makes
toolsa required parameter, which is a hard filter underrequire_parameters.- messages ChatMessage[]
Optional. Supplied only so content filters and the sticky prefix hash can be evaluated; nothing is sent to a provider. Omit them and
content_filtercomes back null rather than a fabricatedallow.- session_id string
Sticky-routing key, as on the chat route.
- prompt_cache_key string
- routing_stability enum
- One of: adaptive, sticky, pinned
- routing_seed string
Seeds the weighted draw so a preview is reproducible and quotable in a bug report. Named
routing_seed, notseed: the latter is OpenAI's sampling seed on the chat route, and one name for two knobs on sibling endpoints is a trap.
Responses
- requested stringrequired
- strategy string
direct,fallbackfor amodels[]chain, orlatestfor a~alias.- would_dispatch booleanrequired
Whether a real request with this body would reach a provider at all.
- limit_warning string | null
Set when the key is at or past a SOFT ceiling: the request would be served, with this sentence in its
x-autonomous-relay-limit-warningheader.- refusal object | null
Why not, in the order the pipeline refuses: a budget binds before a filter runs, and both before routing is consulted. Null when
would_dispatchis true.- ordering enum
Whether
cascadeis the order or one draw from it.§8.9.1's default ranking is a weighted random shuffle, deliberately: a deterministic cheapest-first router starves every provider but one. So
sampledmeans the real request draws again and may order the platform attempts differently — reproduce this draw with the samerouting_seed.deterministicmeans the order is fixed (an explicitsort, a:floor/:nitrovariant, or too few platform attempts to shuffle) and a real request will match it.One of: deterministic, sampled- routing_seed string
The seed this preview actually used, echoed so an unseeded call is still reproducible.
- winner RoutePreviewCandidate | null
- cascade RoutePreviewCandidate[]required
The endpoints a real request would try, in order, after the sticky hoist and cut to the same fallback depth.
- beyond_fallback_depth integer
Endpoints that survived every filter but sit past the fallback depth: eligible, and still unreachable.
- endpoints object
- refused object[]
One entry per excluded endpoint, carrying the FIRST constraint that removed it.
unsatisfied_filterssays which constraints emptied the set; this says which endpoints each one cost you.- unsatisfied_filters string[]
The same strings §7.7's 404 would carry.
- unresolved_models string[]
Slugs in the chain that named no model we have — a typo, or a model since withdrawn.
- guardrails object
- content_filter object | null
Null when no
messageswere supplied.labelsname the detectors that matched; the matched text never travels.- sticky object
Run an evaluation
A dataset, a task and up to 8 models (at most 400 cells), producing a scored comparison with per-cell cost and latency (§17.6). Every cell is a real POST /v1/chat/completions on your credentials -- the same rate limit, budgets, guardrails, routing and billing as if you had sent it, and a request row of its own -- so an evaluation is the same account, keys and routing you would run in production. A cell your rate limit refuses waits for the window and is tried again.
The answer streams as NDJSON: one {"type": "cell", ...} line per cell as it completes (four at a time), then {"type": "summary", ...} per model. Nothing is stored: the dataset arrives with the request, the outputs go back in the stream, and there is no run to fetch later.
Scorers: none, exact and contains (against each item's expected; case and spacing ignored unless case_sensitive), and json (the answer parses as JSON, code fences allowed). There is no regex scorer: a caller's pattern run over a model's answer can stall a backtracking engine, so pattern scoring waits for a linear-time one.
Authentication
Inference key (ar-v1-…) · Dashboard session
Request body
- models string[]required
- dataset object[]required
- task object
- scorer object
Responses
Catalog
Models, their endpoints and providers. Public.
List models
Public. Rate limited per client address: 120 a minute, 20,000 a day.
Authentication
None: this endpoint is public.
Parameters
- limit integer · query
Page size.
- offset integer · query
Rows to skip.
- q string · query
A case-insensitive substring of the name or id.
- model_authors string · query
Comma-separated authors, e.g.
anthropic,openai.- context integer · query
Minimum context length, in tokens.
- output_modalities string · query
Comma-separated; the model produces ANY of them:
text,image,audio,video,embedding,rerank. Other values are ignored.- input_modalities string · query
Comma-separated; the model accepts ALL of them:
text,image,file,audio,video. Other values are ignored.- max_prompt_price number · query
The most the cheapest endpoint may charge for input, in USD per million tokens.
total_countcounts after it.- free enum · query
true: only models whose every price is zero (the catalogue'sis_free).- sort enum · query
Anything else sorts by id.
Responses
- id stringrequired
author/slug.- canonical_slug string
- name stringrequired
- created integer | null
Unix seconds.
- description string | null
- context_length integer | null
- architecture object | null
Input and output modalities.
- supported_parameters string[] | null
- default_parameters object | null
- resale_permitted enum
- One of: yes, no, via_reseller, unknown
- byok_only boolean
- is_free boolean
- deprecation_date string | null
- pricing object
The cheapest endpoint's price. Present on the list only.
Get a model
Public and rate limited, as the list is. pricing is absent here; the endpoints route has every endpoint's prices.
Authentication
None: this endpoint is public.
Parameters
- author string · pathrequired
e.g.
anthropic.- slug string · pathrequired
e.g.
claude-sonnet-5.
Responses
- id stringrequired
author/slug.- canonical_slug string
- name stringrequired
- created integer | null
Unix seconds.
- description string | null
- context_length integer | null
- architecture object | null
Input and output modalities.
- supported_parameters string[] | null
- default_parameters object | null
- resale_permitted enum
- One of: yes, no, via_reseller, unknown
- byok_only boolean
- is_free boolean
- deprecation_date string | null
- pricing object
The cheapest endpoint's price. Present on the list only.
List a model's endpoints
Public and rate limited. Every provider serving the model, with its price, measured uptime and latency, and tool-call reliability.
Authentication
None: this endpoint is public.
Parameters
- author string · pathrequired
e.g.
anthropic.- slug string · pathrequired
e.g.
claude-sonnet-5.
Responses
A model's availability per provider over the last week
Public and rate limited. For each provider that served the model in the last 7 UTC days, one figure per day: the share of dispatches it answered without failing on its side (a 5xx, unreachable, a broken stream). A caller's own errors -- a bad request, their key's rate limit -- do not count against it. A day with fewer than min_dispatches dispatches, or from fewer than min_organizations organisations, is null: not measured.
Authentication
None: this endpoint is public.
Parameters
- author string · pathrequired
e.g.
anthropic.- slug string · pathrequired
e.g.
claude-sonnet-5.
Responses
How a model's input and output prices have changed, per provider
Public and rate limited. One series per provider and SKU (prompt, completion), oldest first: each point is a USD-per-token price and the time it took effect (from) and was replaced (to, null for the current price). Prices are effective-dated, so every change since the catalogue began recording them is here; an unchanged price written again is one point.
Authentication
None: this endpoint is public.
Parameters
- author string · pathrequired
e.g.
anthropic.- slug string · pathrequired
e.g.
claude-sonnet-5.
Responses
Everything the home page shows
Public and rate limited, cached 30 seconds. The first 60 models, the providers, the purchase fee schedule, and the endpoints of the first six models -- each exactly as its own operation returns it. A part that could not be read is null; an endpoints read that failed is left out.
Authentication
None: this endpoint is public.
Responses
- models object | nullrequired
- providers Provider[] | nullrequired
- fees object | nullrequired
- endpoints object[]required
Whether free models work without a provider key here
Public and rate limited. Whether this deployment serves the catalogue's free models without a provider key of your own, on its own key: available, the daily request limit per organisation, and the models it applies to. available is false, and models empty, when it does not -- then every model, free ones included, runs on your own provider key.
Authentication
None: this endpoint is public.
Responses
- available boolean
- daily_limit integer
- models string[]
Models added and prices changed in the catalogue lately
Public and rate limited. Ready models added in the last days days (default 30, at most 90), newest first, and every input (prompt) or output (completion) per-token price that changed on an endpoint in that window -- rises and drops -- with the price before and after, in USD per token. A change is the importer replacing an endpoint's price: the same definition the price_drop alert uses.
Authentication
None: this endpoint is public.
Parameters
- days integer · query
Responses
Ask to be emailed when a model's price drops
Public; no account. Double opt-in: the address is sent one confirmation email, and nothing else until its link is clicked; an unconfirmed request is deleted after 7 days. Once confirmed, an email is sent when the model's input or output price drops on any provider -- once per drop, several models' drops in one email -- each with a one-click unsubscribe link. The answer is the same 202 whether or not an email was sent (an address already subscribed, over its limit of 20 models or of requests per day), so it says nothing about any address. Rate limited per client address and per email address.
Authentication
None: this endpoint is public.
Parameters
- author string · pathrequired
e.g.
anthropic.- slug string · pathrequired
e.g.
claude-sonnet-5.
Request body
- email stringrequired
The address to email.
- lang enum
The language of the emails. Default
en.One of: en, fr
Responses
- status enumrequired
- One of: check_inbox
- message stringrequired
Whether price-drop emails can be requested here
Public. available is false on a deployment with no email configured, where subscribing answers 503.
Authentication
None: this endpoint is public.
Responses
- available booleanrequired
Confirm a price-drop email subscription
The link in the confirmation email. Valid for 7 days, and idempotent while valid. Redirects to the model's page with price_alert=confirmed, or to /models?price_alert=invalid for an unknown or expired link.
Authentication
The token in the link we sent (query parameter token)
Parameters
- token string · queryrequired
From the confirmation email.
Responses
Unsubscribe from price-drop emails (link)
The link in every price-alert email; no sign-in. Deletes the subscription -- or, for an email's "stop all" link, every subscription of the address -- and the address once it has none. Redirects to the model's page (or /models) with price_alert=unsubscribed, or price_alert=invalid for a link already used or unknown. Never refused by region: it only deletes.
Authentication
The token in the link we sent (query parameter token)
Parameters
- token string · queryrequired
From the email.
Responses
Unsubscribe from price-drop emails (one-click, RFC 8058)
What a mail client POSTs to the List-Unsubscribe URL, with the body List-Unsubscribe=One-Click (form-encoded; ignored). The same deletion as the link.
Authentication
The token in the link we sent (query parameter token)
Parameters
- token string · queryrequired
From the email's List-Unsubscribe header.
Responses
- unsubscribed booleanrequired
List providers
Public and rate limited.
Authentication
None: this endpoint is public.
Responses
- slug stringrequired
- name stringrequired
- hq_country string | null
- datacenters string[] | null
- privacy_policy_url string | null
- tos_url string | null
- status_page_url string | null
- models_served integer
In
GET /v1/providersonly: how many ready models the provider has an active endpoint for -- the modelsGET /v1/providers/{slug}lists. Zero for a provider in the directory that serves nothing yet.
Model rankings by tokens processed
Public and rate limited. Tokens processed per model -- prompt, completion, reasoning and cache, by the model that served them -- over day (since 00:00 UTC), week (7 days), month (30 days), or trending (the largest increase, this week against the week before). A measure of use, not of quality. Aggregated only, and a model is listed only once at least min_organizations (3) distinct organisations used it in the period; in trending, last week's figure is null when last week was below that threshold too. Recomputed at most every ten minutes.
Authentication
None: this endpoint is public.
Parameters
- range enum · query
day,week(default),monthortrending.
Responses
- rank integer
- model string
- name string | null
- author string | null
- tokens integer
- share number
- available boolean
Whether the model is still in the catalogue. A retired model keeps its rank, since usage is history, but has no page to link to.
- prior_tokens integer | null
Trending only.
- change_tokens integer | null
Trending only.
The apps directory: apps by tokens processed
Public and rate limited. Apps are what requests name in HTTP-Referer; each is listed by its domain only (paths merged, www. dropped) -- never the X-Title or categories a caller sends, which anyone can set. A domain is listed once it has at least min_requests (100) completed requests in the period; apps whose first request sent X-App-Visibility: hidden never are, nor are local or private hosts. week (7 days, the default) or month (30). Recomputed at most every ten minutes.
Authentication
None: this endpoint is public.
Parameters
- range enum · query
week(default) ormonth.
Responses
- rank integer
- domain string
- tokens integer
- top_models string[]
- retired_models string[]
Get a provider and the models it serves
Public and rate limited. The directory row, and every ready model the provider has an active endpoint for, with the endpoint's prompt and completion price, context, quantization, region and published uptime -- the same figures as the model's own endpoints list.
Authentication
None: this endpoint is public.
Parameters
- slug string · pathrequired
e.g.
anthropic.
Responses
Keys
API keys.
Inspect the calling key
For an inference key: its limit, what remains of it, and what it has spent plus what its in-flight requests have reserved.
Authentication
Inference key (ar-v1-…)
Responses
- label string | null
- limit number | null
The key's spend limit in USD, or null for none.
- limit_remaining number | null
Ceiling minus usage, measured exactly as the spend gate measures it: within the reset window, including spend on your own provider credential only when include_byok_in_limit is set, plus the worst-case reservation of every request on this key still in flight -- released or replaced by the actual amount at settlement, so this can go down. Not a billing total -- see /v1/credits for money.
- usage number
Spend counted against this key ceiling, measured exactly as the spend gate measures it: within the reset window, including spend on your own provider credential only when include_byok_in_limit is set, plus the worst-case reservation of every request on this key still in flight -- released or replaced by the actual amount at settlement, so this can go down. Not a billing total -- see /v1/credits for money.
- limit_reset string | null
- limit_mode enum
hard(the default) refuses a request once the key is at or past its ceiling, with 403budget_exceeded.softserves it and adds anx-autonomous-relay-limit-warningheader carrying the same sentence.One of: hard, soft- include_byok_in_limit boolean
Count spend made on your own provider credential toward this ceiling, at IMPUTED LIST PRICE -- what the call would have cost on platform capacity, not the platform fee charged. Defaults to true: every model is BYOK-only, so a ceiling that skipped this spend would count nothing and could never bind. Set false to count only platform spend.
- rpm_limit integer | null
The key's own requests per minute, counted in calendar minutes on top of the account quota; null for none. Inference keys only.
- tpm_limit integer | null
The key's own tokens (prompt + completion) per minute; null for none. Requests are refused once the minute's count reaches it, and a request's tokens are counted when it finishes, so requests in flight can overshoot it. Inference keys only.
- is_free_tier boolean
List keys
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- include_disabled boolean · query
Include revoked keys.
Responses
- hash string
Identifies the key in
DELETE /v1/keys/{hash}. Not the key itself.- prefix string
- name string | null
- label string | null
- class enum
- One of: inference, management
- disabled boolean
- limit number | null
USD.
- limit_nanodollars string | null
The same limit, raw.
- limit_reset string | null
- limit_mode enum
hard(the default) refuses a request once the key is at or past its ceiling, with 403budget_exceeded.softserves it and adds anx-autonomous-relay-limit-warningheader carrying the same sentence.One of: hard, soft- include_byok_in_limit boolean
- rpm_limit integer | null
The key's own requests per minute, counted in calendar minutes on top of the account quota; null for none. Inference keys only.
- tpm_limit integer | null
The key's own tokens (prompt + completion) per minute; null for none. Requests are refused once the minute's count reaches it, and a request's tokens are counted when it finishes, so requests in flight can overshoot it. Inference keys only.
- cache_enabled boolean
Whether this key's non-streaming chat completions are answered from the response cache. Off by default.
- cache_ttl_seconds integer
How long an answer stays cached. Kept while the cache is off.
- workspace_id string | null
The workspace (client) the key belongs to.
- usage number | null
USD counted against the ceiling in its current window, measured exactly as the spend gate measures it (see KeyInfo.usage). Null for a key with no ceiling, or a revoked one.
- limit_remaining number | null
Ceiling minus usage. Negative when a soft ceiling has been passed. Null when there is no ceiling.
- limit_resets_at string | null
When the current window ends. Null for a lifetime ceiling or none.
- created_at string
- updated_at string
- expires_at string | null
- external_user string | null
Create a key
The plaintext key is in this response and never again: only a salted hash is stored.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- name string
- limit number
A spend limit in USD. Omit for none.
- limit_reset string | null
The window the ceiling covers, in UTC calendar terms. Null means lifetime: the ceiling never resets.
One of: daily, weekly, monthly, lifetime, null- limit_mode enum
hard(the default) refuses a request once the key is at or past its ceiling, with 403budget_exceeded.softserves it and adds anx-autonomous-relay-limit-warningheader carrying the same sentence.One of: hard, softDefault: "hard"- include_byok_in_limit boolean
Count spend on your own provider credential toward the ceiling, at list price. On by default: every model is BYOK-only, so without it the ceiling would count nothing.
Default: true- workspace_id string
Put the key in this workspace (client). Omit for the caller's own workspace. Another organisation's id is a 404.
- class enum
- One of: inference, managementDefault: "inference"
- expires_at string
When the key stops authenticating (401
key_expired). With a time zone, in the future, within ten years. Omit for a key that does not expire.- rpm_limit integer | null
The key's own requests per minute, counted in calendar minutes on top of the account quota; null for none. Inference keys only.
- tpm_limit integer | null
The key's own tokens (prompt + completion) per minute; null for none. Requests are refused once the minute's count reaches it, and a request's tokens are counted when it finishes, so requests in flight can overshoot it. Inference keys only.
- cache_enabled boolean
Answer this key's repeated non-streaming chat completions from the response cache, at no cost. Inference keys only. An identical request gets the same answer, whatever its temperature.
Default: false- cache_ttl_seconds integer
How long an answer stays cached.
Default: 3600
Responses
- key stringrequired
The key. Store it now.
- hash stringrequired
- name string | null
- class enumrequired
- One of: inference, management
- expires_at string | null
- rpm_limit integer | null
The key's own requests per minute, counted in calendar minutes on top of the account quota; null for none. Inference keys only.
- tpm_limit integer | null
The key's own tokens (prompt + completion) per minute; null for none. Requests are refused once the minute's count reaches it, and a request's tokens are counted when it finishes, so requests in flight can overshoot it. Inference keys only.
- cache_enabled boolean
- cache_ttl_seconds integer
Change a key's spend limit, rates or expiry, or pause and resume it
Changes the ceiling, its window, its mode, whether BYOK spend counts, the key's requests and tokens per minute, the workspace, a pause or the expiry. Only these: a key's class, name and secret are fixed at creation. At least one field is required. The new ceiling applies at once on the instance serving this call and within the auth cache's 10-second TTL everywhere else.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- hash string · pathrequired
The key's
hash, from the list.- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- limit number | null
The new ceiling in USD; null removes it.
- limit_reset string | null
The window the ceiling covers, in UTC calendar terms. Null means lifetime: the ceiling never resets.
One of: daily, weekly, monthly, lifetime, null- limit_mode enum
hard(the default) refuses a request once the key is at or past its ceiling, with 403budget_exceeded.softserves it and adds anx-autonomous-relay-limit-warningheader carrying the same sentence.One of: hard, soft- include_byok_in_limit boolean
- workspace_id string
Move the key to this workspace of the same organisation.
- paused boolean
false resumes a key paused by a runaway flag or by hand; true pauses it by hand. A paused key answers 403
key_paused.- expires_at string | null
Set or move the expiry (with a time zone, in the future, within ten years); null removes it. Refused on the calling key and on a dashboard sign-in key, which would lock their holder out.
- rpm_limit integer | null
The key's own requests per minute, counted in calendar minutes on top of the account quota; null for none. Inference keys only.
- tpm_limit integer | null
The key's own tokens (prompt + completion) per minute; null for none. Requests are refused once the minute's count reaches it, and a request's tokens are counted when it finishes, so requests in flight can overshoot it. Inference keys only.
- cache_enabled boolean
Turn the response cache on or off for this key. Inference keys only. Turning it off stops lookups at once; entries already stored expire on their TTL, or go now with
DELETE /v1/cache.- cache_ttl_seconds integer
How long answers stored from now on stay cached.
Responses
- hash stringrequired
- name string | null
- class enum
- One of: inference, management
- limit number | null
USD.
- limit_reset string | null
- limit_mode enum
- One of: hard, soft
- include_byok_in_limit boolean
- paused boolean
- paused_reason enum
- One of: runaway, manual, null
- expires_at string | null
- rpm_limit integer | null
The key's own requests per minute, counted in calendar minutes on top of the account quota; null for none. Inference keys only.
- tpm_limit integer | null
The key's own tokens (prompt + completion) per minute; null for none. Requests are refused once the minute's count reaches it, and a request's tokens are counted when it finishes, so requests in flight can overshoot it. Inference keys only.
- cache_enabled boolean
- cache_ttl_seconds integer
Revoke a key
Disables the key and ends every dashboard session it created.
Propagation is bounded at 10 seconds (§17.4: "publish that TTL"). The instance serving this call stops accepting the key immediately; any other instance stops within the auth cache's TTL. That cache serves no stale window — past ten seconds the entry is refused and the caller waits on the database — so ten seconds is the real bound, not the point at which a refresh merely begins.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- hash string · pathrequired
The key's
hash, from the list.- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- deleted anyrequired
Describe the response cache
The organisation's live response-cache entries and their size. The cache is turned on per inference key (cache_enabled); available is false while the deployment does not run it, in which case nothing is cached whatever a key says.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- available booleanrequired
- entries integerrequired
- bytes integerrequired
The size of the stored answers, before encryption.
Purge the response cache
Deletes every cached answer of the organisation at once; the next request of each kind is a miss. Owner and Admin only (org:write).
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- deleted integerrequired
Entries deleted.
Usage
What was requested, and what it cost.
List recent requests
Newest first, keyset-paginated. Cost is summed per row, over the window.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- limit integer · query
Page size.
- days integer · query
The window, ending now.
- cursor string · query
The
next_cursorof the previous page. Opaque; do not parse it.- model string · query
The model that served.
- provider string · query
A provider slug.
- workspace string · query
One client: a workspace id. A malformed id is a 400.
- agent string · query
One agent: the X-Autonomous-Relay-Agent value.
- tag string · query
Requests a classifier tagged with this.
- status string · query
The request status, e.g.
complete.- byok boolean · query
BYOK requests only, or none.
- app string · query
An
app_id.
Responses
- id string
- created_at string
- requested_model string
- served_model string | null
Null until routing picks one; differs from
requested_modelwhen a fallback fired.- provider_slug string | null
- status string
- finish_reason string | null
Normalized to five values.
native_finish_reasoncarries the provider's own.One of: stop, length, tool_calls, content_filter, error, null- native_finish_reason string | null
- is_byok boolean
- is_cache_hit boolean
- cancelled boolean
- streamed boolean
- quantization string | null
- ttft_ms integer | null
- generation_ms integer | null
- routing_overhead_ms integer | null
Total time minus upstream provider time -- the latency this gateway added (§18). Null when nothing was dispatched, and on rows recorded before it was measured.
- error_code string | null
The provider's own code where a provider refused, or a
router.*reason code where this gateway is what failed -- a credential it could not open, a request it could not express. A stream that broke after it had committed is recorded on the upstream attempt, not here.- error_message string | null
The failure in English, for a developer. Where a provider refused, this names the provider, its HTTP status and its error code -- never the provider's own text, which can quote the prompt and is returned only in the response to the request itself. Where this gateway failed, its own sentence.
- total_cost number
US dollars.
- app_id string | null
- app_title string | null
- http_referer string | null
- workspace_id string | null
The client (workspace) of the key that made the request.
- agent string | null
The X-Autonomous-Relay-Agent the request named, if any.
- tags string[]
Export a month of requests as CSV
One row per request in a UTC calendar month, for the account or one client (workspace). Columns: created_at, request_id, client, key, requested_model, served_model, provider, status, error_code, byok, prompt_tokens, completion_tokens, billed_usd (what this account was charged), list_price_usd (the tokens at catalogue list price: under BYOK, the number a client is re-billed on and the one budgets measure) and agent. Text cells that a spreadsheet would run as a formula are prefixed with a single quote. Capped at 200,000 rows, after which a # truncated line ends the file. At most 6 exports a minute per key.
Needs the Pro ($29/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- month string · query
YYYY-MM, UTC. Default: the current month.
- workspace string · query
One client: a workspace id. Another organisation's is a 404.
Responses
Query usage analytics
Aggregates over your requests and what they cost -- the rows Activity and Logs read, so the numbers agree. Name at least one metric, up to two dimensions to group by, up to twenty filters on dimensions, a time range (default the last 7 days, at most 92) and a granularity for a series. group_limit keeps the top groups by the first metric over the whole range, so a series has the same groups in every bucket. GET /v1/analytics/meta lists every metric and dimension. A seat limited to some workspaces queries those alone.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- metrics string[]required
e.g.
requests,spend_usd,total_tokens,error_rate,avg_ttft_ms.- dimensions string[]
e.g.
model,provider,api_key,workspace,agent.- filters object[]
- time_range object
- granularity enum
- One of: none, hour, day, week, monthDefault: "none"
- limit integer
- Default: 1000
- group_limit integer
- order_by object
Responses
List analytics metrics and dimensions
Every metric, dimension, filter operator and granularity POST /v1/analytics/query accepts, and its limits.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- metrics object[]
- dimensions object[]
- operators string[]
- granularities string[]
- limits object
List analytics metrics and dimensions (alias)
The same as GET /v1/analytics/meta, under the name the design requirements use.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- metrics object[]
- dimensions object[]
- operators string[]
- granularities string[]
- limits object
Scrape usage as Prometheus metrics
The caller's organisation in the Prometheus text exposition format (version 0.0.4), for a Prometheus scrape_config with the management key as bearer_token. Counters count finished requests since the start of the current UTC month and reset to zero at each month boundary, which rate() and increase() treat as an ordinary counter reset; autonomousrelay_counters_since_timestamp_seconds says when. Families: autonomousrelay_requests_total{model,provider,status}, autonomousrelay_tokens_total{model,provider,type} (type is prompt or completion), autonomousrelay_spend_usd_total{model,provider} (USD billed), the autonomousrelay_request_duration_seconds{model,provider} histogram, and the autonomousrelay_active_keys{class} gauge. The 25 models with the most requests keep their own model label; the rest are summed as other. A seat limited to some workspaces sees those alone. Computed at most every 15 seconds per organisation; a faster scrape reads the same numbers.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
Get activity totals
The KPI cards (§14.9), with the prior period of equal length beside them and a daily series for the sparklines. Both periods are read in one pass, so they cannot disagree about where "now" was.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- days integer · query
The window, ending now. The prior period is the same length again.
- workspace string · query
One client: a workspace id. A malformed id is a 400.
Responses
- requests integer
- errors integer
Requests that ended with an error code. Counted zero on deployments older than the reason codes, where no code was recorded.
- byok_requests integer
- spend number
US dollars.
- tokens integer
Prompt plus completion.
cache_readandreasoningare subsets of those and are not added again.- prompt_tokens integer
- cached_tokens integer
Prompt tokens served from the provider's cache -- a subset of
prompt_tokens.- cache_hit_rate number | null
cached_tokens / prompt_tokens. Null when there were no prompt tokens, which is not the same as a rate of zero.- blended_per_million number | null
USD per million tokens, blended across every model and provider in the window. Null when there were no tokens.
Get one request
Everything recorded about one request (§14.10): the list row, plus the key that made it, its session and run, the usage lines it was billed on, and every dispatch to a provider in order. Metadata only -- stored content is GET /v1/generation/{id}/content. Another organisation's id is a 404.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The request id (
gen-…).
Responses
List upstream provider requests
One row per dispatch to a provider, newest first and keyset-paginated. A request that failed over twice appears three times -- filter by request to see a single generation's attempts in order.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- limit integer · query
Page size.
- days integer · query
The window, ending now.
- cursor string · query
The
next_cursorof the previous page. Opaque; do not parse it.- workspace string · query
One client: a workspace id. The dispatches made for its requests. A malformed id is a 400.
- request string · query
A generation id: every dispatch made for it.
- provider string · query
A provider slug.
- status enum · query
Whether the dispatch committed.
Responses
- id string
Opaque; the row's identity, not the request's.
- request_id string
The generation this dispatch was made for. Several rows share it when a fallback fired.
- created_at string
- attempt integer
1-indexed position in the cascade.
- model_id string
- provider_slug string
- endpoint_id string
- is_byok boolean
- status enum
Whether the dispatch committed. A stream that shipped bytes and then failed is
okwith anerror_message.One of: ok, error- http_status integer | null
The upstream status. Null when the dispatch never reached the provider.
- error_code string | null
The provider's own code where the provider answered, or a
router.*reason code where this gateway is what failed -- a credential it could not open, a request it could not express, a stream that broke after it had committed.- error_message string | null
As on the request: the provider, status and code where the provider refused; never its own text.
- duration_ms integer | null
Time inside the provider call. Null when nothing was dispatched.
- ttft_ms integer | null
List conversations
Generations grouped by session_id, most recently active first. Only requests that carried one are included.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- limit integer · query
Page size.
- days integer · query
The window, ending now.
- cursor string · query
The
next_cursorof the previous page. Opaque; do not parse it.- workspace string · query
One client: a workspace id. A malformed id is a 400.
Responses
- session_id string
- generations integer
Requests in this conversation, within the window.
- errors integer
- started_at string
- last_seen_at string
- spend number
US dollars.
- tokens integer
- models string[]
Every model the conversation was served by. More than one means it switched mid-session.
- providers string[]
Get one request's record
Which endpoint served it, at which price version, and what each SKU cost -- enough to recompute the charge.
Not the content. Prompts and completions are stored only when your organisation has enabled input/output logging (§13.1), which is off by default and never retroactive; when it is on, the content is read from GET /v1/generation/{id}/content, not from here.
Authentication
Inference key (ar-v1-…)
Parameters
- id string · queryrequired
The
idof a chat completion.
Responses
- id string
- model string | null
The model that served.
- provider_name string | null
- endpoint_id string | null
- quantization string | null
- total_cost number
US dollars.
- finish_reason string | null
Normalized to five values.
native_finish_reasoncarries the provider's own.One of: stop, length, tool_calls, content_filter, error, null- native_finish_reason string | null
- streamed boolean
- cancelled boolean
- is_byok boolean
- latency integer | null
Time to first token, in milliseconds.
- generation_time integer | null
Milliseconds.
- price_version_ids integer[]
- usage_lines object[]
- app_id string | null
- app_title string | null
- http_referer string | null
Scheme and host only. The path, query string and fragment are never stored on a request, because that is where an app puts the user it is serving.
- user_agent string | null
- created_at string
Get one generation's stored prompt and completion
§13.1. Returns content only if your organisation had input/output logging enabled when the generation was made.
Stored encrypted (AES-256-GCM, data key wrapped by Cloud KMS) in a table separate from request metadata, under an AAD bound to your organisation — a credential ciphertext cannot be read here and content cannot be read from the credential path. Deleted automatically past your configured retention.
This is the only read path for stored content, and it is yours. §13.1 forbids using it for training or analytics, and there is no internal reader.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The generation id (
gen-…).- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- request_id stringrequired
- content objectrequired
The request messages, the completion, and any tool calls.
Read a generation's scores
Every score your organisation's keys attached to the generation, oldest first; an empty list when there are none. Another organisation's id is a 404.
Authentication
Inference key (ar-v1-…)
Parameters
- id string · queryrequired
The generation id (
gen-…).
Responses
- id stringrequired
The generation id (
gen-…).- value numberrequired
From -1 to 1: thumbs down -1, thumbs up 1.
- label string | nullrequired
A slug such as
helpful, or null.- yours booleanrequired
Whether the calling key submitted this score. Which key did is never returned.
- created_at stringrequired
- updated_at stringrequired
Score a generation
Attach a score to a request your organisation made, so you can see which models your users rate well. value is a number from -1 to 1 -- thumbs down -1, thumbs up 1, a finer rating mapped into the range. label is an optional slug (helpful, wrong_answer).
One score per generation per key: posting again from the same key replaces it. Any inference key of the organisation that made the request may score it, as any may read it with GET /v1/generation; another organisation's id is a 404.
No free text. A comment is refused with a 400: a comment is content an end user typed, and the gateway stores no content.
Authentication
Inference key (ar-v1-…)
Request body
- id stringrequired
The generation id (
gen-…).- value numberrequired
- label string | null
Responses
- id stringrequired
The generation id (
gen-…).- value numberrequired
From -1 to 1: thumbs down -1, thumbs up 1.
- label string | nullrequired
A slug such as
helpful, or null.- yours booleanrequired
Whether the calling key submitted this score. Which key did is never returned.
- created_at stringrequired
- updated_at stringrequired
Feedback by model
The average score and the number of scores, by the model that served the request, over requests made in the last days days (default 30, at most 90). Most-scored first, at most 100 models. A workspace-limited person sees their workspaces' requests only.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- days integer · query
The window, ending now, by when the request was made.
Responses
- model stringrequired
- count integerrequired
- average numberrequired
- positive integerrequired
Scores above 0.
- negative integerrequired
Scores below 0.
Credits
Balance and purchases.
Get the balance
Held credits are reserved by requests in flight and are shown apart from the available balance.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- total_credits number
US dollars.
- held_credits number
US dollars.
- available_credits number
US dollars.
- credit_line number
US dollars.
Get the purchase fee schedule
Public. While nothing a credit can buy exists (BYOK-only), purchasable is false and the fee is reported as 0.
Authentication
None: this endpoint is public.
Responses
- fee_bps integer
Basis points.
- fee_min number
US dollars.
- min_purchase number
US dollars.
- configured boolean
A payment processor is configured.
- purchasable boolean
A purchased balance could actually be spent.
List purchases
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- limit integer · query
Page size.
- cursor string · query
The
next_cursorof the previous page. Opaque; do not parse it.
Responses
- id string
- created_at string
- provider string
- status string
- gross number
US dollars.
- fee number
US dollars.
- net number
US dollars.
- tax_jurisdiction string | null
- has_document boolean
Get a purchase's invoice or receipt
Resolved from Stripe on demand; only the checkout session id is stored.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
A purchase
id.
Responses
- kind enum
- One of: invoice, receipt
- url string
- pdf_url string | null
- number string | null
Start a credit purchase
Returns a Stripe Checkout URL. Refused with 409 while credits cannot be spent (BYOK-only, zero fee) -- checked before the body is read.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- amount numberrequired
USD.
Responses
- url string
- id string
- fee number
US dollars.
Receive a Stripe event
For Stripe, not for you. Credits on checkout.session.completed and checkout.session.async_payment_succeeded only when payment_status is paid, once per session; logs async_payment_failed; acknowledges everything else with 200.
Authentication
Stripe signature
Responses
- received anyrequired
Billing
The plans, per organisation, any number of members; inference is never marked up. A 14-day trial of Team, then Pro ($29/month): guardrails (create, assign), presets, classifiers, usage-alert channels (not the runaway setting, a safety control) and the CSV export; Team ($99): Pro plus invitations, workspace members, a second workspace, report branding and client reports; Business ($399): Team plus single sign-on and SCIM; Enterprise: an invoiced annual contract. Without a plan the core keeps working -- inference on your own provider keys, API keys, activity, logs, members, the first workspace. Creating or changing a feature the plan does not include answers 402 `subscription_required`, naming the plan it needs. What was set up keeps running, stays readable and can be deleted.
The organisation's plan
trial (Team's features) for 14 days from creation; then the paid plan while its subscription is active, trialing or past_due (Stripe retrying a renewal): pro ($29/month: guardrails, usage alerts, exports, presets, classifiers), team ($99: Pro plus members, more workspaces and client reports), business ($399: Team plus SSO and SCIM), or enterprise (an invoiced annual contract, set up per customer in Stripe with tier: enterprise in the subscription metadata); limited otherwise. Each plan includes the ones before it. A feature the plan does not include answers 402 subscription_required when created or changed, naming the plan it needs; what was set up keeps working. Readable by every role.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- state enum
- One of: trial, pro, team, business, enterprise, limited
- trial_ends_at string
- trial_days_left integer
- subscription object | null
{ status, current_period_end }once the organisation has subscribed; Stripe's own status word.- price object
This plan's monthly price; Team's while the organisation has no self-serve plan.
- plans object[]
Every plan the organisation can subscribe to, cheapest first.
- configured boolean
False when STRIPE_SECRET_KEY is unset: subscribing answers 503.
Subscribe to a plan
Returns a Stripe Checkout URL for the plan named in plan -- pro ($29), team ($99, the default) or business ($399) a month, per organisation, card only. The plan changes when Stripe's webhook confirms the payment, not when this URL is created. Owner, Admin or Finance.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- plan enum
Defaults to
team.One of: pro, team, business
Responses
- url string
Change plan
Moves a live Pro, Team or Business subscription to another of the three. The new price is prorated on the next invoice. Answers 202: the plan changes when Stripe's customer.subscription.updated arrives, usually within seconds. Enterprise is set by contract and is not changed here. Owner, Admin or Finance.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- plan enumrequired
- One of: pro, team, business
Responses
- plan enum
- One of: pro, team, business
- status enum
- One of: pending
- note string
Open the billing portal
Returns a Stripe billing portal URL: the card, invoices, and cancelling. Owner, Admin or Finance.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- url string
BYOK
Your provider credentials. Required before anything routes.
List provider credentials
Keys are never returned, by this or any route -- only key_hint.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
- provider_slug string
- name string | null
- key_hint string
The last characters of the key. The key itself is never returned.
- tier enum
- One of: prioritized, fallback
- priority integer
- fallback_policy enum
- One of: platform, none_for_models, none_for_provider
- model_filter object
- allowed_models string[] | null
Model ids or
*patterns, ANDed withmodel_filter.- allowed_api_key_hashes string[] | null
Only these API keys (their
hash, asGET /v1/keyslists it) may use the credential.- allowed_user_ids string[] | null
Only keys these members are behind -- created, or signed in with -- may use the credential. A key no person is behind is outside the list.
- disabled boolean
- created_at string
- last_used_at string | null
Add a provider credential
Encrypted with a per-credential key before it is stored. Nothing routes until you have one for the provider that serves your model.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- provider stringrequired
A provider slug with an adapter, e.g.
anthropic.- api_key stringrequired
- name string
- tier enum
- One of: prioritized, fallback
- priority integer
- fallback_policy enum
- One of: platform, none_for_models, none_for_provider
- model_filter object
- allowed_models string[] | null
Model ids or
*patterns, ANDed withmodel_filter.- allowed_api_key_hashes string[] | null
Only these API keys (their
hash, asGET /v1/keyslists it) may use the credential.- allowed_user_ids string[] | null
Only keys these members are behind -- created, or signed in with -- may use the credential. A key no person is behind is outside the list.
Responses
- id string
- provider_slug string
- name string | null
- key_hint string
The last characters of the key. The key itself is never returned.
- tier enum
- One of: prioritized, fallback
- priority integer
- fallback_policy enum
- One of: platform, none_for_models, none_for_provider
- model_filter object
- allowed_models string[] | null
Model ids or
*patterns, ANDed withmodel_filter.- allowed_api_key_hashes string[] | null
Only these API keys (their
hash, asGET /v1/keyslists it) may use the credential.- allowed_user_ids string[] | null
Only keys these members are behind -- created, or signed in with -- may use the credential. A key no person is behind is outside the list.
- disabled boolean
- created_at string
- last_used_at string | null
Enable, disable or scope a provider credential
disabled and the three scope fields can change; a field left out is unchanged, null makes it unrestricted. To change the key, add a new credential and delete this one.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
A credential
id.- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- disabled boolean
- allowed_models string[] | null
Model ids or
*patterns, ANDed withmodel_filter.- allowed_api_key_hashes string[] | null
Only these API keys (their
hash, asGET /v1/keyslists it) may use the credential.- allowed_user_ids string[] | null
Only keys these members are behind -- created, or signed in with -- may use the credential. A key no person is behind is outside the list.
Responses
- id string
- provider_slug string
- name string | null
- key_hint string
The last characters of the key. The key itself is never returned.
- tier enum
- One of: prioritized, fallback
- priority integer
- fallback_policy enum
- One of: platform, none_for_models, none_for_provider
- model_filter object
- allowed_models string[] | null
Model ids or
*patterns, ANDed withmodel_filter.- allowed_api_key_hashes string[] | null
Only these API keys (their
hash, asGET /v1/keyslists it) may use the credential.- allowed_user_ids string[] | null
Only keys these members are behind -- created, or signed in with -- may use the credential. A key no person is behind is outside the list.
- disabled boolean
- created_at string
- last_used_at string | null
Delete a provider credential
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
A credential
id.- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- deleted anyrequired
Alerts
Usage alerts: where you are told a key is nearing its spend ceiling.
List usage-alert channels
Where the organisation is told that a key crossed a share of its spend ceiling. email_available says whether this deployment can send email. A webhook's signing secret is never returned here: only once, when the channel is created.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
- kind enum
- One of: webhook, slack, email
- target string
- name string | null
- thresholds integer[]
- events enum[]
What the channel receives.
usage(the default): key and agent limit crossings and runaway flags.price_drop: a model this organisation used in the last 30 days got cheaper (input or output tokens), announced once, within 15 minutes of the change.- disabled boolean
- created_at string
Add a usage-alert channel
A key crossing any of thresholds (percent of its ceiling, default 50, 80 and 100), or an agent crossing them on one of its budgets (agent_limit.threshold), is announced once per threshold per ceiling window, on every channel that lists that threshold; a key that jumps several thresholds in one request is announced once, at the highest. A webhook target must be a public https URL on the default port; a slack target must be a https://hooks.slack.com/... incoming-webhook URL; email needs the deployment to be configured for it. Webhook deliveries are JSON, signed in x-autonomous-relay-signature: t=<unix>,v1=<hex>, where v1 is HMAC-SHA256 of <t>.<raw body> with the channel's signing_secret. At most 20 channels per organisation.
Needs the Pro ($29/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- kind enumrequired
- One of: webhook, slack, email
- target stringrequired
An https URL, or an email address for
email.- name string
- thresholds integer[]
Whole percentages from 1 to 100. Default [50, 80, 100].
- events enum[]
What the channel receives.
usage(the default): key and agent limit crossings and runaway flags.price_drop: a model this organisation used in the last 30 days got cheaper (input or output tokens), announced once, within 15 minutes of the change.
Responses
- id string
- kind enum
- One of: webhook, slack, email
- target string
- name string | null
- thresholds integer[]
- events enum[]
What the channel receives.
usage(the default): key and agent limit crossings and runaway flags.price_drop: a model this organisation used in the last 30 days got cheaper (input or output tokens), announced once, within 15 minutes of the change.- disabled boolean
- created_at string
Change what a channel receives
Only events: a new target is a new channel. Changing events keeps the channel and its webhook signing secret. A price_drop event is JSON {type, model, provider, sku, old_usd_per_million, new_usd_per_million, effective_at, at}, with x-autonomous-relay-event: price_drop, signed as every other delivery is.
Needs the Pro ($29/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The channel id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- events enum[]required
What the channel receives.
usage(the default): key and agent limit crossings and runaway flags.price_drop: a model this organisation used in the last 30 days got cheaper (input or output tokens), announced once, within 15 minutes of the change.
Responses
- id string
- kind enum
- One of: webhook, slack, email
- target string
- name string | null
- thresholds integer[]
- events enum[]
What the channel receives.
usage(the default): key and agent limit crossings and runaway flags.price_drop: a model this organisation used in the last 30 days got cheaper (input or output tokens), announced once, within 15 minutes of the change.- disabled boolean
- created_at string
Remove a usage-alert channel
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The channel id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- deleted anyrequired
Send a test alert
Delivers a test event now and reports the outcome, so a wrong URL or a receiver that rejects the payload shows at once. The attempt is recorded in the delivery log.
Needs the Pro ($29/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The channel id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- status enumrequired
- One of: sent, failed, skipped
- http_status integer | null
What the receiver answered, when it answered.
- error string | null
Why it failed, in our words. The receiver's response body is never read.
What a runaway flag does
alert: every flag is sent to the alert channels and nothing else happens (the default). pause: a flagged KEY is also paused -- it answers 403 key_paused until resumed with PATCH /v1/keys/{hash} {"paused": false}. An agent flag is never a pause: a tag is not a credential.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- runaway_action enumrequired
- One of: alert, pause
Choose what a runaway flag does
Requires config:write (Developer or above): this decides whether a heuristic may stop production traffic.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- runaway_action enumrequired
- One of: alert, pause
Responses
- runaway_action enumrequired
- One of: alert, pause
Runaway-spend flags
A key or an agent (X-Autonomous-Relay-Agent) flagged because its last 15 minutes were far above its own previous 24 hours: spend at least 3x its usual 15 minutes and at least $5, or requests at least 5x usual and at least 300. Checked every five minutes; a subject is flagged at most once an hour, and each flag is sent to every alert channel as a spend.runaway event. With runaway_action = pause (see /v1/alerts/settings) a flagged key is also paused; action says which happened. The last 30 days, at most 100.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
- subject_kind enum
- One of: key, agent
- subject string
The agent tag, or the first 12 characters of the key hash.
- key_name string | null
- key_hash string | null
The full hash, for PATCH /v1/keys/{hash}; null for an agent.
- key_paused boolean
Whether the key is paused right now (by this flag, a later one, or by hand).
- action enum
What the sweep did with this flag.
One of: alert, paused- kind enum
- One of: spend, rate
- window_start string
- window_end string
- spend number
US dollars.
- usual_spend number
US dollars.
- requests integer
- usual_requests number
- created_at string
Recent alert deliveries
The last 50 delivery attempts, newest first, each with its outcome. Kept for 90 days.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
- channel_id string | null
Null once the channel has been removed.
- channel_name string | null
- channel_kind string | null
- event enum
- One of: key_limit.threshold, agent_limit.threshold, spend.runaway, run.paused, connection.skipped, price_drop, ledger.drift, test
- threshold integer | null
- status enum
- One of: sent, failed, skipped
- http_status integer | null
- error string | null
- key_name string | null
- key_hash_prefix string | null
- agent_tag string | null
For an agent-budget alert: the X-Autonomous-Relay-Agent value.
- created_at string
Files
Upload once, refer to by id. Off unless the deployment enables it, pending a privacy review.
List files
Unexpired files, newest first, as {"object": "list", "data": [...]}. Off unless the deployment sets FILES_ENABLED=true: uploaded files are customer content at rest, which waits on a privacy review; until then every files route is a 403 saying so.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
file-…- object enum
- One of: file
- bytes integer
- created_at integer
- expires_at integer
- filename string
- purpose string
- mime_type string
What the bytes are, whatever the name says.
- status enum
- One of: processed
Upload a file
OpenAI's shape: multipart/form-data with file, purpose (user_data, assistants or vision) and optionally expires_after[seconds] (3,600 to 2,592,000; default 30 days). A PDF, a PNG, JPEG, GIF or WebP image, or UTF-8 text, at most 10 MB, typed by its bytes; 500 MB per organisation. Stored encrypted. Use it in a completion as {"type": "file", "file": {"file_id": "file-…"}}. Inference key, or a person with config:write. Off unless the deployment sets FILES_ENABLED=true: uploaded files are customer content at rest, which waits on a privacy review; until then every files route is a 403 saying so.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
file-…- object enum
- One of: file
- bytes integer
- created_at integer
- expires_at integer
- filename string
- purpose string
- mime_type string
What the bytes are, whatever the name says.
- status enum
- One of: processed
Get a file's details
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The file id (
file-…).
Responses
- id string
file-…- object enum
- One of: file
- bytes integer
- created_at integer
- expires_at integer
- filename string
- purpose string
- mime_type string
What the bytes are, whatever the name says.
- status enum
- One of: processed
Delete a file
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The file id.
Responses
- id string
- object enum
- One of: file
- deleted boolean
Download a file
The bytes, as an attachment, to the organisation that uploaded them.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The file id.
Responses
Videos
Video generation jobs: submit, poll, download. Off unless the deployment enables it, pending a privacy review.
List videos
The organisation's jobs, newest first, as {"object": "list", "data": [...]}. Off unless the deployment sets VIDEO_ENABLED=true: a finished video is generated content stored for 24 hours, which waits on a privacy review; until then every video route is a 403 saying so.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
video_…- object enum
- One of: video
- model string
- provider string
- status enum
- One of: queued, in_progress, completed, failed
- created_at integer
- completed_at integer | null
- expires_at integer
- seconds number | null
- error object | null
- generation_id string
The request id;
GET /v1/generation?id=reads it.- usage object
Generate a video
OpenAI's video shape: submits a job and answers at once with a video object, status: "queued". Poll GET /v1/videos/{id} until it is completed (or failed), then download GET /v1/videos/{id}/content. Generation takes minutes.
Routed and admitted like every other call -- model, models and provider as on chat completions, the same budgets, content filters (a redacted prompt is what is generated) and guardrails -- with a hold sized at $0.60 a second of video asked for, then billed on the provider's reported cost of the generation, since video prices vary by resolution, audio and length. seconds (1 to 15) is sent in each model's own field; parameters carries the model's other fields as given (resolution, aspect ratio, negative prompt, seed...).
Off unless the deployment sets VIDEO_ENABLED=true: a finished video is generated content stored for 24 hours, which waits on a privacy review; until then every video route is a 403 saying so.
Authentication
Inference key (ar-v1-…) · Dashboard session
Parameters
- X-Autonomous-Relay-Agent string · header
The agent this request is for, as on chat completions.
Request body
- model string
A text-to-video model id from
/v1/models.- models string[]
Fallbacks, tried in order after
model.- prompt stringrequired
- seconds integer
- parameters object
The model's own fields, at most 30 and 8 KB; not
promptorwebhook.- provider object
Routing preferences, as on chat completions.
Responses
- id string
video_…- object enum
- One of: video
- model string
- provider string
- status enum
- One of: queued, in_progress, completed, failed
- created_at integer
- completed_at integer | null
- expires_at integer
- seconds number | null
- error object | null
- generation_id string
The request id;
GET /v1/generation?id=reads it.- usage object
Get a video job
Its status -- queued, in_progress, completed or failed -- and, once known, what it cost. A job the provider has not reported on within two hours is failed and its hold given back.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The video id (
video_…).
Responses
- id string
video_…- object enum
- One of: video
- model string
- provider string
- status enum
- One of: queued, in_progress, completed, failed
- created_at integer
- completed_at integer | null
- expires_at integer
- seconds number | null
- error object | null
- generation_id string
The request id;
GET /v1/generation?id=reads it.- usage object
Delete a video
The job and its video. A job still being generated is a 409: its result is still due.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The video id.
Responses
- id string
- object enum
- One of: video
- deleted boolean
Download a video
The finished video, within 24 hours of its completion: the bytes as an attachment when the provider delivered them (stored encrypted), or a 302 to the provider's own link when it delivered one (the link is stored encrypted; the video stays with the provider). Follow redirects.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The video id.
Responses
Receive a provider's video result
For the provider, not for you: the webhook a video job is submitted with. Authenticated by the job's secret token in the URL, compared in constant time against its hash; an unknown job or a wrong token is a bare 404. A delivery for a job already handled is acknowledged and changes nothing, so the provider's retries settle a job once.
Authentication
The token in the link we sent (query parameter token)
Parameters
- id string · pathrequired
The video id.
- token string · queryrequired
The job's callback secret.
Responses
- ok anyrequired
Batches
Chat requests run through the provider's own batch API, at its batch price, within 24 hours.
List batches
The organisation's batches, newest first, as last checked.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
batch_…- object enum
- One of: batch
- endpoint enum
- One of: /v1/chat/completions
- model string
The
:batchmodel.- provider string
- status enum
- One of: in_progress, completed, failed, cancelled, expired
- created_at integer
- completed_at integer | null
- expires_at integer
- request_counts object
- errors object | null
- generation_id string
The request id;
GET /v1/generation?id=reads its cost.- usage object
Create a batch
Up to 10,000 chat-completion requests, run by the provider's own batch API -- OpenAI's Batch API, Anthropic's Message Batches, Google's Gemini batch mode, Mistral's batch jobs, Alibaba Model Studio's Batch API, xAI's Batch API -- at its batch price (the catalogue's :batch models, typically half the live price), within 24 hours, on your own provider key. Name the model (openai/gpt-5.4 or openai/gpt-5.4:batch); every request uses it.
Each request is {custom_id, body}, the body a chat completion without model or stream. The requests pass the same budgets, guardrails and content filters as live ones -- every message text is filtered, and what a filter redacts is what is submitted -- and the hold is the worst case of all of them. Server tools are refused: they run inside a live request.
Poll GET /v1/batches/{id}; once it has ended it is billed, once, on the sum of its requests' usage at the batch price, and GET /v1/batches/{id}/results streams the outcomes. Nothing of the requests or results is stored here: the provider holds them, under your account, for its own retention.
Authentication
Inference key (ar-v1-…) · Dashboard session
Parameters
- X-Autonomous-Relay-Agent string · header
The agent this batch is for, as on chat completions.
Request body
- model stringrequired
A chat model with a
:batchrow in/v1/models, named with or without the suffix.- requests object[]required
- endpoint enum
- One of: /v1/chat/completions
- completion_window enum
- One of: 24h
- provider object
Routing preferences, as on chat completions.
Responses
- id string
batch_…- object enum
- One of: batch
- endpoint enum
- One of: /v1/chat/completions
- model string
The
:batchmodel.- provider string
- status enum
- One of: in_progress, completed, failed, cancelled, expired
- created_at integer
- completed_at integer | null
- expires_at integer
- request_counts object
- errors object | null
- generation_id string
The request id;
GET /v1/generation?id=reads its cost.- usage object
Get a batch
Its status, asking the provider when the last answer is over 30 seconds old. The first look after it has ended bills it -- once -- and usage.cost appears.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The batch id (
batch_…).
Responses
- id string
batch_…- object enum
- One of: batch
- endpoint enum
- One of: /v1/chat/completions
- model string
The
:batchmodel.- provider string
- status enum
- One of: in_progress, completed, failed, cancelled, expired
- created_at integer
- completed_at integer | null
- expires_at integer
- request_counts object
- errors object | null
- generation_id string
The request id;
GET /v1/generation?id=reads its cost.- usage object
Get a batch's results
JSON Lines, one per request, in OpenAI's batch output shape: {custom_id, response: {status_code, body: <chat completion>}, error}, or {custom_id, response: null, error: {code, message}}. Read from the provider as it is sent; nothing is kept.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The batch id.
Responses
Cancel a batch
Asks the provider to stop it. Requests already done are still billed when it ends.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The batch id.
Responses
- id string
batch_…- object enum
- One of: batch
- endpoint enum
- One of: /v1/chat/completions
- model string
The
:batchmodel.- provider string
- status enum
- One of: in_progress, completed, failed, cancelled, expired
- created_at integer
- completed_at integer | null
- expires_at integer
- request_counts object
- errors object | null
- generation_id string
The request id;
GET /v1/generation?id=reads its cost.- usage object
Classifiers
Organisation rules that tag each request from content-free signals, and may route a match through a preset.
List classifiers
Organisation rules that tag each request from content-free signals, in the order they run. Any role may read this.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
- name string
- tag string
- priority integer
- conditions ClassifierConditions
- preset string | null
- enabled boolean
- created_at string
- updated_at string
Create a classifier
Every enabled classifier whose conditions all hold gives the request its tag (stored on the request, shown in /v1/activity, sent back as x-autonomous-relay-tags). The first matching one that names a preset routes the request through it. Conditions read only content-free signals: the model the request named, the key, the client, the agent, the app, whether tools or images are present, streaming and the prompt's size. config:write.
Needs the Pro ($29/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Request body
- name stringrequired
- tag stringrequired
Lower-case letters, digits and hyphens, at most 40. Unique per organisation.
- priority integer
Lower runs first; decides which matching classifier routes.
Default: 100- conditions ClassifierConditionsrequired
- preset string | null
A preset slug to route a matching request through. A request naming its own @preset/… keeps it.
- enabled boolean
Responses
- id string
- name string
- tag string
- priority integer
- conditions ClassifierConditions
- preset string | null
- enabled boolean
- created_at string
- updated_at string
Replace a classifier
Needs the Pro ($29/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The classifier id.
Request body
- name stringrequired
- tag stringrequired
Lower-case letters, digits and hyphens, at most 40. Unique per organisation.
- priority integer
Lower runs first; decides which matching classifier routes.
Default: 100- conditions ClassifierConditionsrequired
- preset string | null
A preset slug to route a matching request through. A request naming its own @preset/… keeps it.
- enabled boolean
Responses
- id string
- name string
- tag string
- priority integer
- conditions ClassifierConditions
- preset string | null
- enabled boolean
- created_at string
- updated_at string
Delete a classifier
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The classifier id.
Responses
- id string
- deleted boolean
Try a sample request
Which classifiers a request with these signals would match, and which would route it. Nothing is sent.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Request body
- model string
- key_name string
- workspace_id string
- agent string
- app string
- has_tools boolean
- has_images boolean
- stream boolean
- prompt_tokens integer
Responses
- tags string[]
- route object | null
Plugins
The plugin marketplace: MCP servers their developers host, reviewed for listing, installed per organisation and offered to the model with {"type": "autonomousrelay:plugin", "plugin": "<slug>"}.
List the plugin marketplace
Public and rate limited. Every approved plugin: what it is, who publishes it, how an install authenticates (none, api_key or oauth2), its categories and logo. Not where it runs.
Authentication
None: this endpoint is public.
Responses
- id string
- slug string
- name string
- summary string
- description string | null
- publisher string
- official boolean
Built by Autonomous Relay: a platform organisation owns it.
- built_by string
The name to show: Autonomous Relay when official, else the publisher.
- homepage_url string | null
- privacy_url string | null
- auth enum
- One of: none, api_key, oauth2
- categories string[]
- icon_url string | null
The logo, on this origin, or null when it has none.
One approved plugin
Its listing and, for a connector, what it does: the tools it offers (write ones wait for approval), the events it sends and what it keeps where.
Authentication
None: this endpoint is public.
Parameters
- slug string · pathrequired
The plugin's slug.
Responses
- id string
- slug string
- name string
- summary string
- description string | null
- publisher string
- official boolean
Built by Autonomous Relay: a platform organisation owns it.
- built_by string
The name to show: Autonomous Relay when official, else the publisher.
- homepage_url string | null
- privacy_url string | null
- auth enum
- One of: none, api_key, oauth2
- categories string[]
- icon_url string | null
The logo, on this origin, or null when it has none.
- connector object | null
What a connector says it does, from its manifest; null for a plain plugin.
An approved plugin's logo
Public. The image itself, under its own type, cached a day; the listing's icon_url changes when the logo does.
Authentication
None: this endpoint is public.
Parameters
- slug string · pathrequired
The plugin's slug.
Responses
List the plugins your organisation publishes
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
- slug string
- name string
- summary string
- description string | null
- publisher string
- official boolean
Built by Autonomous Relay: a platform organisation owns it.
- built_by string
The name to show: Autonomous Relay when official, else the publisher.
- homepage_url string | null
- privacy_url string | null
- auth enum
- One of: none, api_key, oauth2
- categories string[]
- icon_url string | null
The logo, on this origin, or null when it has none.
- oauth_authorize_url string | null
- oauth_token_url string | null
- oauth_client_id string | null
- oauth_scopes string | null
- has_client_secret boolean
- mcp_url string
- auth_header string | null
- status enum
- One of: private, pending, approved, rejected, suspended
- review_note string | null
- reviewed_at string | null
- created_at string
- updated_at string
Register a plugin
A plugin is an MCP server you host (Streamable HTTP, public https). It starts private: your organisation can install and use it at once to build and test it; submit it for review to be listed publicly. One a super admin registers is the platform's own and is listed for every organisation at once. auth: api_key means each installing organisation pastes a key you give them, sent in auth_header (default Authorization). Agent tools -- tools that run many steps on your side and answer once -- are called like any tool, with up to 120 seconds per call. At most 20 plugins per organisation.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Request body
- slug string
2-40 lowercase letters, digits or hyphens; fixed once created.
- name string
- summary string
At most 280 characters.
- description string | null
- publisher string
- homepage_url string | null
- privacy_url string | null
- mcp_url string
Your MCP endpoint: public https, Streamable HTTP.
- auth enum
- One of: none, api_key, oauth2
- oauth_authorize_url string
oauth2: your authorization endpoint (public https).
- oauth_token_url string
oauth2: your token endpoint (public https).
- oauth_client_id string
oauth2: the client id you issued us.
- oauth_client_secret string
oauth2, confidential clients: write-only, sealed, never returned.
- oauth_scopes string
oauth2: the scope string to request.
- auth_header string
For api_key: the header the key is sent in. Default Authorization.
- categories enum[]
- icon string | null
The logo:
data:image/png;base64,..., or JPEG, WebP or SVG, at most 64 KB decoded. An SVG may not carry scripts or event handlers. null removes it.
Responses
- id string
- slug string
- name string
- summary string
- description string | null
- publisher string
- official boolean
Built by Autonomous Relay: a platform organisation owns it.
- built_by string
The name to show: Autonomous Relay when official, else the publisher.
- homepage_url string | null
- privacy_url string | null
- auth enum
- One of: none, api_key, oauth2
- categories string[]
- icon_url string | null
The logo, on this origin, or null when it has none.
- oauth_authorize_url string | null
- oauth_token_url string | null
- oauth_client_id string | null
- oauth_scopes string | null
- has_client_secret boolean
- mcp_url string
- auth_header string | null
- status enum
- One of: private, pending, approved, rejected, suspended
- review_note string | null
- reviewed_at string | null
- created_at string
- updated_at string
Edit a plugin you publish
Any listing field but the slug. Sending publisher, mcp_url, auth, auth_header or an oauth_* field sends an approved plugin back to review -- unlisted, and unusable by other organisations, until approved again -- unless a super admin sends it. A logo or a client secret alone never does.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The plugin id.
Request body
- slug string
2-40 lowercase letters, digits or hyphens; fixed once created.
- name string
- summary string
At most 280 characters.
- description string | null
- publisher string
- homepage_url string | null
- privacy_url string | null
- mcp_url string
Your MCP endpoint: public https, Streamable HTTP.
- auth enum
- One of: none, api_key, oauth2
- oauth_authorize_url string
oauth2: your authorization endpoint (public https).
- oauth_token_url string
oauth2: your token endpoint (public https).
- oauth_client_id string
oauth2: the client id you issued us.
- oauth_client_secret string
oauth2, confidential clients: write-only, sealed, never returned.
- oauth_scopes string
oauth2: the scope string to request.
- auth_header string
For api_key: the header the key is sent in. Default Authorization.
- categories enum[]
- icon string | null
The logo:
data:image/png;base64,..., or JPEG, WebP or SVG, at most 64 KB decoded. An SVG may not carry scripts or event handlers. null removes it.
Responses
- id string
- slug string
- name string
- summary string
- description string | null
- publisher string
- official boolean
Built by Autonomous Relay: a platform organisation owns it.
- built_by string
The name to show: Autonomous Relay when official, else the publisher.
- homepage_url string | null
- privacy_url string | null
- auth enum
- One of: none, api_key, oauth2
- categories string[]
- icon_url string | null
The logo, on this origin, or null when it has none.
- oauth_authorize_url string | null
- oauth_token_url string | null
- oauth_client_id string | null
- oauth_scopes string | null
- has_client_secret boolean
- mcp_url string
- auth_header string | null
- status enum
- One of: private, pending, approved, rejected, suspended
- review_note string | null
- reviewed_at string | null
- created_at string
- updated_at string
Delete a plugin you publish
Every installation of it goes with it.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The plugin id.
Responses
The logo of a plugin you publish
Listed or not, as its icon_url in your own list points to. usage:read.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The plugin id.
Responses
Read the plugin's connector manifest
Fetches /.well-known/autonomousrelay-connector.json from the plugin's MCP origin through the SSRF guard, checks it, and stores it: capabilities, each tool's mode (a tool counts as read-only only if this and its readOnlyHint both say so) and context keys, the events it sends, its handshake_url (on its own origin, required when it sends events) and what it stores. The plugin's owner, config:write.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The plugin id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- name string
- version string
- capabilities string[]
- tools object[]
- events object[]
- handshake_url string | null
- uninstall_url string | null
Told when an organisation removes the install, so the connector erases what it holds for it.
- data_residency object[]
Give a connector install a new events token
The gateway mints an events token and POSTs {install_id, events_url, events_token} to the manifest's handshake_url with the install's own credential, as tool calls carry it. Done at install; this retries after a failure or rotates the token. The old token works until the connector accepts the new one. config:write.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The install id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- id string
- events_ready boolean
Post an event from a connector
For connectors: Authorization: Bearer <events token> from the install handshake. The event must be one the manifest declares, with only its declared context keys and field names; id is the platform's own event id, and a repeat within a day answers 200 {duplicate: true}. Each active plugin_event trigger of the install and type starts a run, as its own key and inside its own caps. Nothing is stored but the id. Off unless the deployment sets HOSTED_AGENTS_ENABLED=true.
Authentication
Connector events token (bearer)
Request body
- type stringrequired
e.g. order.created
- id stringrequired
The platform's event id.
- occurred_at string
- context object
- fields object
Responses
- duplicate boolean
- id string
- id string
- runs string[]
- skipped object[]
Submit a plugin for review
It waits in the queue for a super admin. A super admin's own submission is listed for every organisation at once, as Official.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The plugin id.
Responses
- id string
- slug string
- name string
- summary string
- description string | null
- publisher string
- official boolean
Built by Autonomous Relay: a platform organisation owns it.
- built_by string
The name to show: Autonomous Relay when official, else the publisher.
- homepage_url string | null
- privacy_url string | null
- auth enum
- One of: none, api_key, oauth2
- categories string[]
- icon_url string | null
The logo, on this origin, or null when it has none.
- oauth_authorize_url string | null
- oauth_token_url string | null
- oauth_client_id string | null
- oauth_scopes string | null
- has_client_secret boolean
- mcp_url string
- auth_header string | null
- status enum
- One of: private, pending, approved, rejected, suspended
- review_note string | null
- reviewed_at string | null
- created_at string
- updated_at string
Install a plugin for your organisation
{id} is the plugin's slug. An approved plugin, or one your organisation publishes. For an api_key plugin, credential is the key its developer gave you: sealed at rest, sent only to the plugin, only its last four characters shown again. Then offer it in a request with {"type": "autonomousrelay:plugin", "plugin": "<slug>"} in tools. The plugin is a recipient you choose: it receives the tool arguments the model writes.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The plugin's slug.
Request body
- credential string
Responses
- id string
- enabled boolean
- credential_hint string | null
- created_at string
- events_ready_at string | null
Connectors: when the install last received its events token.
- handshake_error string | null
Connectors: why the last handshake failed.
- connected boolean
Whether it holds what it needs to run: an OAuth connection's tokens or a key. Always true for a plugin that takes neither.
- connected_at string
- connected_by object | null
Who connected it last; null when no person did, or they have left.
- plugin object
Start connecting an OAuth plugin
{id} is the plugin's slug. For an oauth2 plugin: the answer's authorize_url is the plugin developer's sign-in page (authorization code + PKCE S256); send the person there. Their authorization server returns them to /v1/auth/oauth/plugin/callback, which stores the tokens on your organisation's install (sealed, refreshed before they expire) and sends them back to the dashboard. Whatever the plugin reaches upstream -- a Google account, say -- is granted to its developer there, never to us.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The plugin's slug.
Responses
- authorize_url stringrequired
Where a plugin's authorization server returns
Not called directly. Checks the state against the flow cookie, redeems the code with the PKCE verifier (and the plugin's client secret, if it has one), stores the tokens, and redirects to the dashboard with connected=<slug> or plugin_error=<reason>. Register {PUBLIC_ORIGIN}/v1/auth/oauth/plugin/callback as the redirect URI.
Authentication
The `state` matched to the flow cookie, and the plugin authorization server's code, redeemed with the PKCE verifier.
Responses
An installed plugin's tools, live
{id} is the plugin's slug. Asks the plugin now (tools/list) on your install's credential: the way to check an install works.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The plugin's slug.
Responses
- name string
- description string | null
- input_schema object
Your organisation's installed plugins
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
- enabled boolean
- credential_hint string | null
- created_at string
- events_ready_at string | null
Connectors: when the install last received its events token.
- handshake_error string | null
Connectors: why the last handshake failed.
- connected boolean
Whether it holds what it needs to run: an OAuth connection's tokens or a key. Always true for a plugin that takes neither.
- connected_at string
- connected_by object | null
Who connected it last; null when no person did, or they have left.
- plugin object
Turn an installed plugin off or on
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The install id.
Request body
- enabled booleanrequired
Responses
- id string
- enabled boolean
Uninstall a plugin
Its sealed credential goes with it.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The install id.
Responses
Tools
Server tools: declared in tools[] as {"type": "autonomousrelay:<name>"}, run by the gateway inside the request.
List server tools
Every server tool in the catalogue (§11.2), whether it is available yet, whether it sends request data to a third party, and whether this organisation has it on. Any role may read this. The catalogue is the gateway's own tools; a connection's tools (autonomousrelay:plugin, autonomousrelay:mcp, and autonomousrelay:connected for all of them) are the organisation's, listed by GET /v1/tools/available.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- type string
What a request puts in tools[].type, e.g.
autonomousrelay:datetime.- group enum
- One of: web, multi_model, code, files, utilities
- third_party boolean
Running it sends request data to a third party.
- available boolean
Built. A request declaring an unavailable tool is a 400 naming it.
- enabled boolean
Turn server tools off or on
disabled is the full list of tools to turn off; every available tool not in it is on. A request declaring a tool that is off is refused with a 403 naming it. config:write.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Request body
- disabled string[]required
Responses
- type string
What a request puts in tools[].type, e.g.
autonomousrelay:datetime.- group enum
- One of: web, multi_model, code, files, utilities
- third_party boolean
Running it sends request data to a third party.
- available boolean
Built. A request declaring an unavailable tool is a 400 naming it.
- enabled boolean
List connected tools
Every connection of the key's organisation -- its installed plugins, then its MCP servers, each by name -- with whether it works now and the tools it offers, named as the model sees them: what {"type": "autonomousrelay:connected"} would draw on. Each connection is asked live, in parallel, within 5 seconds. status is ok, not_connected (an OAuth plugin never connected), expired (its connection lapsed: reconnect it), disabled (turned off for the organisation) or unreachable (it did not answer). A plugin that could not be asked shows its stored manifest's tools (tools_source: "manifest", no descriptions); an MCP server that could not be asked shows none. mode is read only when the tool says it is read-only and, for a plugin, its manifest agrees. 30 requests a minute per key.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Responses
- kind enum
- One of: plugin, mcp
- slug string
The plugin's slug, or the MCP server's name: what
includeandexcludetake.- status enum
- One of: ok, not_connected, expired, disabled, unreachable
- tools_source enum
live: asked just now.manifest: the plugin's stored manifest, because it could not be asked.One of: live, manifest, none- tools object[]
List registered MCP servers
Your organisation's own MCP servers (§17.7), whose tools a request can offer the model with {"type": "autonomousrelay:mcp", "server": "<name>"}. Never returns the credential; header_hint is its last four characters. Any role may read this.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
- name string
- url string
- allowed_tools string[] | null
- header_name string | null
- header_hint string | null
- disabled boolean
- created_at string
Register an MCP server
An MCP server reachable over the Streamable HTTP transport, at a public https URL. header_name and header_value are the credential it expects (e.g. Authorization: Bearer …), sealed at rest and sent only on calls to it. allowed_tools limits which of its tools may ever be offered. Owner and Admin only (config:write); at most 20.
The server receives the tool arguments the model writes, which come from your conversation: it is a recipient you choose.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Request body
- name stringrequired
1–32 lowercase letters, digits or hyphens: what a request names it by.
- url stringrequired
Public https; the MCP endpoint itself.
- allowed_tools string[]
- header_name string
A header such as
AuthorizationorX-Api-Key; not one the transport uses.- header_value string
Its value. Sealed at rest; only the last four characters are shown again.
Responses
- id string
- name string
- url string
- allowed_tools string[] | null
- header_name string | null
- header_hint string | null
- disabled boolean
- created_at string
Turn a registered MCP server off or on
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The server id.
Request body
- disabled booleanrequired
Responses
- id string
- name string
- url string
- allowed_tools string[] | null
- header_name string | null
- header_hint string | null
- disabled boolean
- created_at string
Remove a registered MCP server
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The server id.
Responses
List a registered server's tools, live
Asks the server now (tools/list), narrowed to its allowed_tools: the way to check a registration works.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The server id.
Responses
- name string
- description string | null
- input_schema object
Presets
Named, versioned request settings, used as "model": "@preset/<slug>".
List presets
Each preset's current version. Any role may read this.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- slug string
- name string
- description string | null
- version integer
- body object
- reference string
What a request puts in
model:@preset/<slug>.- created_at string
- updated_at string
Create a preset
A named set of request SETTINGS, used as "model": "@preset/<slug>" in a completion (or @preset/<slug>@<version> to pin one). body holds settings only — model, models, temperature, top_p, top_k, max_tokens, seed, provider, reasoning, routing_stability — never messages or a system prompt. A whole request body is accepted: other fields are dropped, named in dropped, and never stored. config:write.
Needs the Pro ($29/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Request body
- slug stringrequired
Lower-case letters, digits and hyphens, at most 64.
- name stringrequired
- description string
- body objectrequired
Responses
Get a preset and its history
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- slug string · pathrequired
The preset slug.
Responses
Save a new version
Every change is a new version; versions are never edited. config:write.
Needs the Pro ($29/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- slug string · pathrequired
The preset slug.
Request body
- body objectrequired
- note string
- name string
- description string | null
Responses
- slug string
- name string
- description string | null
- version integer
- body object
- reference string
What a request puts in
model:@preset/<slug>.- created_at string
- updated_at string
Delete a preset and its history
A request still naming it is then a 404. config:write.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- slug string · pathrequired
The preset slug.
Responses
- slug string
- deleted boolean
Make an old version current again
As a new version with the old one's body, so the history keeps what happened. config:write.
Needs the Pro ($29/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- slug string · pathrequired
The preset slug.
Request body
- version integerrequired
Responses
- slug string
- name string
- description string | null
- version integer
- body object
- reference string
What a request puts in
model:@preset/<slug>.- created_at string
- updated_at string
Observability
Broadcast: a metadata record of each request, sent to your webhook, OpenTelemetry endpoint, S3-compatible bucket, Langfuse or Datadog.
List broadcast destinations
Where a record of each completion is sent (§14.12 Observability). Never returns a signing secret or a header value; header_hint is the value's last four characters. Any role may read this.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
- kind enum
- One of: webhook, otlp, s3, langfuse, datadog
- url string
- name string | null
- sample_rate number
- disabled boolean
- header_name string | null
- header_hint string | null
- s3_region string
s3 only.
- s3_bucket string
s3 only.
- s3_prefix string | null
s3 only.
- s3_path_style boolean
s3 only.
- s3_access_key_id string
s3 only.
- s3_secret_hint string
s3 only: the secret access key's last four characters. The key itself is never returned.
- langfuse_public_key string
langfuse only: the project's public key.
- langfuse_secret_hint string
langfuse only: the secret key's last four characters. The key itself is never returned.
- datadog_site string
datadog only: the Datadog site, e.g.
datadoghq.eu.- datadog_api_key_hint string
datadog only: the API key's last four characters. The key itself is never returned.
- last_attempt_at string | null
- last_success_at string | null
- last_http_status integer | null
- last_error string | null
- created_at string
Add a broadcast destination
After every completion, a record of the request is sent to each destination — metadata only: model, provider, status, tokens, cost, timing, key name, client, agent, session and run; never the prompt or the completion.
webhook: a JSON POST {"type":"request.completed","request":{…}}, signed with X-AgentsRouter-Signature (t=…,v1=hmac_sha256(secret, t + "." + body)); the signing secret is returned once, here. otlp: one OpenTelemetry span per request (OTLP/HTTP JSON, gen_ai.* attributes) to the URL given, which is the full traces endpoint, e.g. https://api.honeycomb.io/v1/traces; header_name and header_value carry the vendor's API key, sealed at rest and never shown again. s3: S3-compatible object storage (AWS S3, Cloudflare R2, Backblaze B2, MinIO, Google Cloud Storage with HMAC keys). url is the endpoint without a bucket, e.g. https://s3.us-east-1.amazonaws.com; records are batched — up to 500 records, 4 MB, or 60 seconds — and each batch is one newline-delimited JSON object (each line the webhook's request.completed record) at {s3_prefix}{YYYY}/{MM}/{DD}/{HH}/{timestamp}-{random}.jsonl, UTC, signed with AWS Signature Version 4. The key needs only s3:PutObject on the bucket; s3_secret_access_key is sealed at rest and never shown again.
langfuse: each request becomes a Langfuse trace with one generation (model, token usage, cost, latency, time to first token, level), sent over OTLP/HTTP JSON to {url}/api/public/otel/v1/traces with Basic auth from langfuse_public_key and langfuse_secret_key; batched up to 100 records or 10 seconds. datadog: each request becomes a log (service:autonomousrelay, ddsource:autonomousrelay, ddtags model:…,provider:…,status:…, the request record as attributes) sent to https://http-intake.logs.{datadog_site}/api/v2/logs with DD-API-KEY; batched up to 500 records or 10 seconds. Both carry metadata only — no prompt or completion.
The URL must be public https. At most 10 destinations; sample_rate sends that fraction of requests. Delivery is after the response, never on the request path. A transient failure (a network error, HTTP 429 or 5xx) is retried up to 3 attempts in all with jittered exponential backoff; any other refusal is final. The final outcome is recorded on the destination (last_error).
Authentication
Management key (ar-mgmt-…) · Dashboard session
Request body
- kind enumrequired
- One of: webhook, otlp, s3, langfuse, datadog
- url stringrequired
Public https. For
s3, the storage endpoint without a bucket or path. Forlangfuse, the Langfuse host (defaulthttps://cloud.langfuse.com; e.g.https://us.cloud.langfuse.comor a self-hosted URL). Not fordatadog, whose intake is derived fromdatadog_site.- name string
- header_name string
webhook and otlp: an HTTP header to send, e.g.
x-honeycomb-teamorAuthorization.- header_value string
Its value. Sealed at rest; only the last four characters are shown again.
- sample_rate number
- Default: 1
- s3_region string
s3, required: the signing region, e.g.
us-east-1;autofor Cloudflare R2.- s3_bucket string
s3, required: the bucket name.
- s3_prefix string
s3: prepended to every object key, e.g.
relay/prod/. At most 256 characters.- s3_path_style boolean
s3:
https://endpoint/bucket/keyrather thanhttps://bucket.endpoint/key. Defaults to false for*.amazonaws.com, true elsewhere; a bucket with dots needs true.- s3_access_key_id string
s3, required.
- s3_secret_access_key string
s3, required. Sealed at rest; only the last four characters are shown again.
- langfuse_public_key string
langfuse, required: the project's public key,
pk-lf-….- langfuse_secret_key string
langfuse, required: the project's secret key,
sk-lf-…. Sealed at rest; only the last four characters are shown again.- datadog_site enum
datadog: the Datadog site of the organisation.
One of: datadoghq.com, us3.datadoghq.com, us5.datadoghq.com, datadoghq.eu, ap1.datadoghq.com, ap2.datadoghq.com, uk1.datadoghq.com, ddog-gov.com, us2.ddog-gov.comDefault: "datadoghq.com"- datadog_api_key string
datadog, required: a Datadog API key (32 hexadecimal characters). Sealed at rest; only the last four characters are shown again.
Responses
Pause, resume, rename or resample a destination
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The destination id.
Request body
- disabled boolean
- sample_rate number
- name string | null
Responses
- id string
- kind enum
- One of: webhook, otlp, s3, langfuse, datadog
- url string
- name string | null
- sample_rate number
- disabled boolean
- header_name string | null
- header_hint string | null
- s3_region string
s3 only.
- s3_bucket string
s3 only.
- s3_prefix string | null
s3 only.
- s3_path_style boolean
s3 only.
- s3_access_key_id string
s3 only.
- s3_secret_hint string
s3 only: the secret access key's last four characters. The key itself is never returned.
- langfuse_public_key string
langfuse only: the project's public key.
- langfuse_secret_hint string
langfuse only: the secret key's last four characters. The key itself is never returned.
- datadog_site string
datadog only: the Datadog site, e.g.
datadoghq.eu.- datadog_api_key_hint string
datadog only: the API key's last four characters. The key itself is never returned.
- last_attempt_at string | null
- last_success_at string | null
- last_http_status integer | null
- last_error string | null
- created_at string
Remove a destination
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The destination id.
Responses
- id string
- deleted boolean
Send a test record now
A synthetic request record, marked as a test, delivered at once; the answer says how the receiver responded. Sent once, without retries. For s3, langfuse and datadog, a batch of that one record is sent straight away, not buffered.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The destination id.
Responses
- delivered boolean
- http_status integer | null
- error string | null
Workspaces
One per client: separate keys, budgets and spend under one account.
List workspaces
One workspace per client is the intended use: each has its own keys, budgets and spend, under one account and one balance. spend_this_month is measured the way a workspace budget is -- settled spend in the current UTC calendar month plus requests in flight, BYOK spend at list price included.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
- name string
- slug string
- description string | null
Up to 500 characters.
- your_role string | null
The caller's workspace role when their seat is limited to workspaces; null for a seat that sees the whole organisation.
- created_at string
- active_keys integer
- spend_this_month number
USD, current UTC calendar month, measured as a workspace budget measures it.
- budgets object[]
- is_current boolean
Whether this is the calling key's own workspace.
Create a workspace
At most 200 per organisation. Put keys in it with workspace_id on POST /v1/keys, or move one with PATCH /v1/keys/{hash}.
Needs the Team ($99/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- name stringrequired
Up to 80 characters, e.g. the client's name.
- description string
Optional, up to 500 characters.
Responses
- id string
- name string
- slug string
- description string | null
Up to 500 characters.
- your_role string | null
The caller's workspace role when their seat is limited to workspaces; null for a seat that sees the whole organisation.
- created_at string
- active_keys integer
- spend_this_month number
USD, current UTC calendar month, measured as a workspace budget measures it.
- budgets object[]
- is_current boolean
Whether this is the calling key's own workspace.
Rename or describe a workspace
Send name, description (null clears it) or both. A seat limited to workspaces needs to be an admin of this one.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The workspace id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- name string
- description string | null
Responses
- id string
- name string
- slug string
- description string | null
Up to 500 characters.
- your_role string | null
The caller's workspace role when their seat is limited to workspaces; null for a seat that sees the whole organisation.
- created_at string
- active_keys integer
- spend_this_month number
USD, current UTC calendar month, measured as a workspace budget measures it.
- budgets object[]
- is_current boolean
Whether this is the calling key's own workspace.
Remove a workspace
Refused with 409 while the workspace has an active key, and for the organisation's last workspace. Revoked keys keep their history and lose the link; provider credentials are never removed with a workspace.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The workspace id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- deleted anyrequired
List a workspace's budgets
An unknown workspace is an empty list, not a 404.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
A workspace id.
Responses
- interval enum
- One of: daily, weekly, monthly, lifetime
- limit_nanodollars string
Nanodollars (1e-9 USD), an integer as a string.
- include_byok boolean
Count spend made on your own provider credential toward this ceiling, at IMPUTED LIST PRICE -- what the call would have cost on platform capacity, not the platform fee charged. Defaults to true: every model is BYOK-only, so a ceiling that skipped this spend would count nothing and could never bind. Set false to count only platform spend.
Set a workspace budget
Budgets must shrink as the interval narrows: a daily budget above the weekly one is refused. Each interval is its own ceiling; they are never summed.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
A workspace id.
- interval enum · pathrequired
The budget's period.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- limit_usd numberrequired
- include_byok boolean
Responses
- workspace_id string
- interval string
- limit_usd number
US dollars.
Delete a workspace budget
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
A workspace id.
- interval string · pathrequired
The budget's period.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- deleted anyrequired
List a workspace's members
The people given a role in this workspace. Membership matters only to seats limited to workspaces (scope: "workspaces" on PATCH /v1/members/{userId}): everyone else sees every workspace.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The workspace id.
Responses
- user_id string
- role enum
- One of: admin, member
- created_at string
- name string | null
- email string | null
- org_role enum
owner = Owner, member = Developer, billing = Finance. What each may do: see the Members tag.
One of: owner, admin, member, billing, readonly- scope enum
workspaces: limited to the workspaces this person is a member of.One of: org, workspaces
Add a workspace member or change their role
A workspace admin can rename it, set its budgets and manage its members; a member can use it (keys, logs, reports). Allowed for an owner or admin of the organisation, or an admin of this workspace. The person must have an active seat.
Needs the Team ($99/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The workspace id.
- userId string · pathrequired
The member's user id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- role enumrequired
- One of: admin, member
Responses
- workspace_id string
- user_id string
- role string
Remove a workspace member
A seat limited to workspaces loses this one at once; with none left, it sees nothing.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The workspace id.
- userId string · pathrequired
The member's user id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- removed boolean
Status
Measured service status.
Measured uptime, last 90 days
From an external probe, not from traffic: a Cloud Monitoring uptime check requests /health (which queries the database) every minute from four regions. One entry per UTC day, oldest first. A day with fewer than 60 probes is uptime: null -- unmeasured, never counted as up. overall is over measured days, weighted by probes, and null when none is measured. Public, limited per client address, cached for a minute.
Authentication
None: this endpoint is public.
Responses
- days object[]
- overall number | null
0 to 1, over measured days.
- measured_days integer
The incident log, last 90 days
Incidents posted by the operator, in English and French: those started in the last 90 days and any still open, newest first, each with its updates oldest first. status is the latest update's; resolved_at is set by the update that resolved it. Written by people, not inferred from the uptime probe. subscriptions.email says whether incident emails can be requested on this deployment. Public, limited per client address, cached for a minute.
Authentication
None: this endpoint is public.
Responses
- id string
- title_en string
- title_fr string
- impact enum
- One of: minor, major, critical
- status enum
- One of: investigating, identified, monitoring, resolved
- started_at string
- resolved_at string | null
- updates object[]
The incident log as an Atom feed
RFC 4287, one entry per update, newest first, over the same incidents as /v1/status/incidents. Follow the status page without giving an email address. Public and cached for a minute.
Authentication
None: this endpoint is public.
Parameters
- lang enum · query
en(default) orfr.
Responses
Ask to be emailed about incidents
Public; no account. Double opt-in: the address is sent one confirmation email, and nothing else until its link is clicked; an unconfirmed request is deleted after 7 days. Once confirmed, every incident and update posted afterwards is emailed once, in the chosen language, each with a one-click unsubscribe link. The answer is the same 202 whether or not an email was sent, so it says nothing about any address. Rate limited per client address and per email address.
Authentication
None: this endpoint is public.
Request body
- email stringrequired
The address to email.
- lang enum
The language of the emails. Default
en.One of: en, fr
Responses
- status enumrequired
- One of: check_inbox
- message stringrequired
Confirm an incident email subscription
The link in the confirmation email. Valid for 7 days, and idempotent while valid. Redirects to the status page with subscription=confirmed, or subscription=invalid for an unknown or expired link.
Authentication
The token in the link we sent (query parameter token)
Parameters
- token string · queryrequired
From the confirmation email.
Responses
Unsubscribe from incident emails (link)
The link in every incident email; no sign-in. Deletes the subscription and the address. Redirects to the status page with subscription=unsubscribed, or subscription=invalid for a link already used or unknown. Never refused by region: it only deletes.
Authentication
The token in the link we sent (query parameter token)
Parameters
- token string · queryrequired
From the email.
Responses
Unsubscribe from incident emails (one-click, RFC 8058)
What a mail client POSTs to the List-Unsubscribe URL, with the body List-Unsubscribe=One-Click (form-encoded; ignored). The same deletion as the link.
Authentication
The token in the link we sent (query parameter token)
Parameters
- token string · queryrequired
From the email's List-Unsubscribe header.
Responses
- unsubscribed booleanrequired
Reports
White-label client reports: the agency's branding, and a client's month as numbers.
Report branding
The name, logo and footer printed on client reports in place of ours. Any role may read it.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- org_name string
The organisation's own name; the fallback when brand_name is unset.
- brand_name string | null
- brand_logo string | null
A PNG or JPEG data URI.
- brand_footer string | null
Set report branding
Owner or Developer. Every field is optional; an absent or empty one clears it. The logo is a PNG or JPEG data URI under 150 KB, checked by its bytes: nothing is ever fetched from a URL, and SVG is refused.
Needs the Team ($99/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- brand_name string | null
Up to 80 characters.
- brand_logo string | null
data:image/png;base64,...ordata:image/jpeg;base64,..., under 150 KB.- brand_footer string | null
Up to 200 characters, e.g. a contact line.
Responses
- org_name string
The organisation's own name; the fallback when brand_name is unset.
- brand_name string | null
- brand_logo string | null
A PNG or JPEG data URI.
- brand_footer string | null
A client's month, as a report
Totals, by model, by agent and by day for one workspace in a UTC calendar month, with the branding to print it under. Amounts are list price -- what the tokens were worth, the number a client is re-billed on and the one budgets measure -- and the same measurement as the CSV export. A usage report, not an invoice: no tax, due date or markup.
Needs the Team ($99/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The workspace id.
- month string · query
YYYY-MM, UTC. Default: the current month.
Responses
- workspace object
- month string
- period object
- branding Branding
- totals ReportLine
- by_model ReportLine[]
- by_agent ReportLine[]
- by_day ReportLine[]
- generated_at string
Audit
The organisation's audit log: who changed what, and when. Owner or Admin.
List the organisation's audit log
Who changed what, and when: keys created, revoked or re-limited; provider keys; guardrails; members invited, re-roled or removed; SSO, SCIM, broadcast, plugins, workspaces, alert channels and organisation settings. Newest first, keyset-paginated. Owner or Admin (a key with no person behind it has full power). The actor is a user id, or for a key with no person behind it the first 12 characters of the key's hash; details holds non-secret facts only -- never a key, a secret, an address or prompt content. Kept for one year.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- limit integer · query
Page size.
- before string · query
The
next_cursorof the previous page. Opaque; do not parse it.- action string · query
One action, e.g.
api_key.revoked, or a category, e.g.api_key.- actor string · query
A user id, or a key reference as the log shows it.
Responses
- id string
- at string
- actor object
- action string
- target object | null
- details object
Members
Team seats. Roles: Owner (everything, including members), Developer (keys, provider keys, limits, workspaces, alerts, agents; reads billing), Finance (usage, exports, credits and checkout; changes nothing else). A management key with no person behind it has full power. Every management route shares one rate limit per key: 300 requests a minute, 20,000 a day (429 past it).
Get the organisation
Its id, name, slug, plan, creation date and number of active seats. Any role may read this.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id stringrequired
- name stringrequired
- slug stringrequired
- plan stringrequired
- created_at stringrequired
- members integerrequired
Active seats.
Rename the organisation
Owner and Admin only (org:write). The name is what invitations and client reports show; the slug and id do not change. Trimmed, 1 to 80 characters, no control characters.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Request body
- name stringrequired
Responses
- id stringrequired
- name stringrequired
- slug stringrequired
- plan stringrequired
- created_at stringrequired
- members integerrequired
Active seats.
List members
Everyone with an active seat in the organisation, owners first, and the caller's own role. Any role may read this, a seat limited to workspaces included.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- user_id string
- role enum
owner = Owner, member = Developer, billing = Finance. What each may do: see the Members tag.
One of: owner, admin, member, billing, readonly- role_name string
- scope enum
workspaces: limited to the workspaces this person is a member of.One of: org, workspaces- joined_at string
- name string | null
- email string | null
- avatar_url string | null
- provider string | null
- is_you boolean
Change a member's role or scope
Owners only. Send role, scope or both. scope: "workspaces" limits a Developer or Read-only seat to the workspaces they are a member of (PUT /v1/workspaces/{id}/members/{userId}); with no memberships they see nothing, never the whole organisation. Owners, admins and Finance always see everything, so moving a seat to one of those roles sets its scope back to org. The organisation's last owner cannot be demoted (409).
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- userId string · pathrequired
The member's user id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- role enum
- One of: owner, member, billing
- scope enum
workspaces: limited to the workspaces this person is a member of.One of: org, workspaces
Responses
- user_id string
- role string
- scope enum
workspaces: limited to the workspaces this person is a member of.One of: org, workspaces
Remove a member
Owners only. The seat is deactivated and the person's dashboard key in this organisation is revoked, ending their sessions here at once; their other organisations are untouched. The last owner cannot be removed (409).
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- userId string · pathrequired
The member's user id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- removed boolean
Open invitations
Owners only. Invitations not yet accepted, revoked or expired. Links are not listed: only their hashes are kept.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
- role string
- created_at string
- expires_at string
- created_by_name string | null
Invite someone
Owners only. Returns a link, in this response and never again: single use, valid seven days, revocable. The invitee opens it, signs in, and accepts. At most 50 open invitations.
Needs the Team ($99/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- role enumrequired
- One of: owner, member, billing
Responses
- id string
- role string
- created_at string
- expires_at string
- url string
The invitation link. Store or send it now.
Revoke an invitation
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The invitation id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- revoked boolean
What an invitation is for
Public, limited per address. The token travels in the body to stay out of access logs. An unknown, used, revoked or expired token all answer the same 404.
Authentication
The invitation token, in the body (kept out of URLs and access logs).
Request body
- token stringrequired
Responses
- org_name string
- role string
- role_name string
- expires_at string
Accept an invitation
Requires a signed-in PERSON (a dashboard session); an API key has no seat and gets 403. Takes the seat, and replaces the session with one in the inviting organisation (Set-Cookie).
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- token stringrequired
Responses
- org_id string
Agents
Agents named in X-Autonomous-Relay-Agent: their spend, and budgets that bind across every key they use.
List agents
Every agent named in X-Autonomous-Relay-Agent in the last 31 days, plus any with a budget but no traffic yet: requests and spend this UTC month (list price included, measured as an agent budget measures it) and budgets. Newest first; at most 500.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- agent string
- last_seen string | null
- requests_this_month integer
- spend_this_month number
US dollars.
- budgets object[]
List hosted agents
Each saved agent's current version: model, tools and run caps. Never the instructions. Any role may read this.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- slug string
Also the
X-Autonomous-Relay-Agenttag every turn carries, so agent budgets apply.- name string
- description string | null
- status enum
- One of: active, paused, archived
- version integer
- model string
A model id or
@preset/<slug>.- tools object[]
- run_defaults object
- approval object
- output object
- invoke string
The path that runs it.
- created_at string
- updated_at string
Create a hosted agent
A saved agent: its instructions, the model or preset it runs on, the tools the gateway may run for it, and the caps every invocation opens a run under (budget_usd, max_turns and max_tool_calls are required). Run it with POST /v1/agents/{slug}/invoke. config:write. Off unless the deployment sets HOSTED_AGENTS_ENABLED=true: storing agent instructions waits on a privacy review, and until then this is a 403 saying so.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- instructions stringrequired
The system prompt, at most 32 KB. Sealed at rest; returned only to config:write.
- model stringrequired
A model id or
@preset/<slug>.- tools object[]
Up to 8, each one the gateway runs:
autonomousrelay:plugin(plugin, optionalallowed_tools),autonomousrelay:mcp(server, optionalallowed_tools), or a built server tool. A plain function is refused: nobody is standing by to run it.- run_defaults objectrequired
- approval object
- output object
- slug stringrequired
Lower-case letters, digits and hyphens, at most 64.
- name stringrequired
- description string
Responses
- slug string
Also the
X-Autonomous-Relay-Agenttag every turn carries, so agent budgets apply.- name string
- description string | null
- status enum
- One of: active, paused, archived
- version integer
- model string
A model id or
@preset/<slug>.- tools object[]
- run_defaults object
- approval object
- output object
- invoke string
The path that runs it.
- created_at string
- updated_at string
Get a hosted agent and its history
instructions is the current version's, and only for config:write; for any other role it is null.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- slug string · pathrequired
The agent slug.
Responses
Save a new version
The whole body again; every change is a new version and versions are never edited, so a run always names what it ran under. config:write. Off unless the deployment sets HOSTED_AGENTS_ENABLED=true: storing agent instructions waits on a privacy review, and until then this is a 403 saying so.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- slug string · pathrequired
The agent slug.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- instructions stringrequired
The system prompt, at most 32 KB. Sealed at rest; returned only to config:write.
- model stringrequired
A model id or
@preset/<slug>.- tools object[]
Up to 8, each one the gateway runs:
autonomousrelay:plugin(plugin, optionalallowed_tools),autonomousrelay:mcp(server, optionalallowed_tools), or a built server tool. A plain function is refused: nobody is standing by to run it.- run_defaults objectrequired
- approval object
- output object
- name string
- description string
- note string
At most 200 characters.
Responses
- slug string
Also the
X-Autonomous-Relay-Agenttag every turn carries, so agent budgets apply.- name string
- description string | null
- status enum
- One of: active, paused, archived
- version integer
- model string
A model id or
@preset/<slug>.- tools object[]
- run_defaults object
- approval object
- output object
- invoke string
The path that runs it.
- created_at string
- updated_at string
Pause, resume or archive a hosted agent
A paused or archived agent refuses invocations with 409; its runs and versions stay. config:write.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- slug string · pathrequired
The agent slug.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- status enumrequired
- One of: active, paused, archived
Responses
- slug string
Also the
X-Autonomous-Relay-Agenttag every turn carries, so agent budgets apply.- name string
- description string | null
- status enum
- One of: active, paused, archived
- version integer
- model string
A model id or
@preset/<slug>.- tools object[]
- run_defaults object
- approval object
- output object
- invoke string
The path that runs it.
- created_at string
- updated_at string
Delete a hosted agent
Deletes every version of its instructions and its triggers, and erases the paused state of any of its runs waiting on an approval, cancelling those runs. Its runs keep their record, without a link to the agent. config:write.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- slug string · pathrequired
The agent slug.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- slug string
- deleted boolean
Run a hosted agent
Opens a run under the agent's caps (an overrides value may lower budget_usd, max_turns or max_tool_calls, never raise one), sends its instructions and your input through POST /v1/chat/completions with its tools and X-Autonomous-Relay-Agent set to the slug, lets the gateway run the tool loop, closes the run and returns the answer. Everything a completion gets applies: presets, guardrails, routing, billing, agent budgets. With stream: true the answer streams as POST /v1/chat/completions does, between two SSE comments of the run's: : autonomousrelay {"type": "run.opened", ...} first and {"type": "run.closed", "run": {...}} just before [DONE]. Nothing is stored but the run's metadata. Off unless the deployment sets HOSTED_AGENTS_ENABLED=true: storing agent instructions waits on a privacy review, and until then this is a 403 saying so.
Authentication
Inference key (ar-v1-…)
Parameters
- slug string · pathrequired
The agent slug.
Request body
- input stringrequired
What the agent is asked to do, at most 100,000 characters.
- overrides object
- stream boolean
- Default: false
Responses
- agent string
- version integer
- status enum
- One of: completed, awaiting_approval
- approval object
- decision enum
On a decision's answer only.
One of: approved, rejected- output string | null
- finish_reason string | null
- model string | null
- generation_id string | null
- usage object
- run object
- agent string
- version integer
- status enum
- One of: completed, awaiting_approval
- approval object
- decision enum
On a decision's answer only.
One of: approved, rejected- output string | null
- finish_reason string | null
- model string | null
- generation_id string | null
- usage object
- run object
List a hosted agent's triggers
Its webhooks and schedules. Never a signing secret. Any role may read this.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- slug string · pathrequired
The agent slug.
Responses
- id string
- kind enum
- One of: webhook, schedule, plugin_event
- name string
- plugin string
plugin_event: the installed plugin's slug.
- event_type string
plugin_event: the event its connector posts.
- key_hash string
The inference key the runs are made as.
- input_template string
The run's input:
{{path}}placeholders filled from the delivery ({{body}}for all of it); on a schedule, fromfired_atandtrigger.- event_id_field string | null
Webhook: where in the delivery the sender's event id is; a repeat within a day starts nothing.
- every_minutes integer | null
Schedule: every this many minutes, 5 to 10080.
- next_fire_at string | null
- max_runs_per_hour integer
- max_concurrent integer
- status enum
- One of: active, paused
- last_fired_at string | null
- url string
Webhook: the path deliveries are posted to.
- created_at string
Start a hosted agent from a webhook or a schedule
A webhook starts a run for each signed delivery to its url; a schedule every every_minutes. Runs are made as the inference key key_hash names -- billed, capped and tagged as that key's, and stopped by revoking or pausing it -- within the agent's run caps and the trigger's own max_runs_per_hour (default 60) and max_concurrent (default 3). A webhook's signing_secret is returned once, here. config:write. Off unless the deployment sets HOSTED_AGENTS_ENABLED=true.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- slug string · pathrequired
The agent slug.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- kind enumrequired
- One of: webhook, schedule, plugin_event
- name stringrequired
- key_hash stringrequired
- plugin string
plugin_event: the installed plugin's slug.
- event_type string
plugin_event: an event the plugin's manifest declares, e.g. order.created.
- input_template stringrequired
At most 4000 characters.
- every_minutes integer
- event_id_field string
A field path, e.g.
idordata.event_id.- max_runs_per_hour integer
- Default: 60
- max_concurrent integer
- Default: 3
Responses
Pause or resume a trigger
Only status; delete and recreate a trigger to change anything else. config:write.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The trigger id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- status enumrequired
- One of: active, paused
Responses
- id string
- kind enum
- One of: webhook, schedule, plugin_event
- name string
- plugin string
plugin_event: the installed plugin's slug.
- event_type string
plugin_event: the event its connector posts.
- key_hash string
The inference key the runs are made as.
- input_template string
The run's input:
{{path}}placeholders filled from the delivery ({{body}}for all of it); on a schedule, fromfired_atandtrigger.- event_id_field string | null
Webhook: where in the delivery the sender's event id is; a repeat within a day starts nothing.
- every_minutes integer | null
Schedule: every this many minutes, 5 to 10080.
- next_fire_at string | null
- max_runs_per_hour integer
- max_concurrent integer
- status enum
- One of: active, paused
- last_fired_at string | null
- url string
Webhook: the path deliveries are posted to.
- created_at string
Delete a trigger
Its runs keep their record. config:write.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The trigger id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- id string
- deleted boolean
Deliver an event to a webhook trigger
Authenticated by X-Autonomous-Relay-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>"> under the trigger's signing secret, valid for five minutes -- the form the gateway's own webhooks carry. The body must be a JSON object, at most 256 KB; it is rendered into the run's input and not stored. Answers 202 with the run's id at once; the run goes on in the background and is on the Runs page. An unknown, paused or badly signed delivery is the same 401.
Authentication
Signature header X-Autonomous-Relay-Signature
Parameters
- id string · pathrequired
The trigger id.
Responses
- duplicate boolean
- event_id string
- run_id string
List hosted agents' pending actions
Actions hosted agents proposed and that wait for, or got, a person's decision. Names only; the arguments are on the action itself, for config:write. Newest first; at most 200. Any role may read this.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- status enum · query
pending(default),approved,rejectedorexpired.
Responses
- id string
- run_id string
- agent string | null
- tools object[]
- status enum
- One of: pending, approved, rejected, expired
- note string | null
- decided_by string | null
- decided_at string | null
- created_at string
- expires_at string
- decide string
The path that decides it.
Get a pending action
calls holds the proposed calls with their arguments while the action is pending, and only for config:write; otherwise null. The arguments are erased when it is decided or expires.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The run id.
- action string · pathrequired
The action id.
Responses
Approve or reject a pending action
Approving runs the proposed calls; rejecting tells the model they were refused (with your note, if any). Either way the run resumes and the conversation continues as the key that invoked the agent -- billed, capped and tagged as any of its turns -- and the answer is what invoke answers, with decision. The held state is erased in the same write that records the decision. config:write. Off unless the deployment sets HOSTED_AGENTS_ENABLED=true.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The run id.
- action string · pathrequired
The action id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- decision enumrequired
- One of: approve, reject
- note string
At most 500 characters. On a rejection, the model is told it.
Responses
- agent string
- version integer
- status enum
- One of: completed, awaiting_approval
- approval object
- decision enum
On a decision's answer only.
One of: approved, rejected- output string | null
- finish_reason string | null
- model string | null
- generation_id string | null
- usage object
- run object
- agent string
- version integer
- status enum
- One of: completed, awaiting_approval
- approval object
- decision enum
On a decision's answer only.
One of: approved, rejected- output string | null
- finish_reason string | null
- model string | null
- generation_id string | null
- usage object
- run object
Set an agent budget
A hard ceiling on one agent's spend in a window, across every key it uses: a request naming the agent is refused with 403 budget_exceeded once the agent is at or past it. Narrower windows must have smaller caps. BYOK spend counts at list price by default.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- agent string · pathrequired
The X-Autonomous-Relay-Agent value.
- interval string · pathrequired
daily,weekly,monthlyorlifetime.- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- limit_usd numberrequired
- include_byok boolean
- Default: true
- mode enum
hardrefuses at the ceiling (403budget_exceeded);softserves, adds the sentence tox-autonomous-relay-limit-warning, and still alerts.One of: hard, softDefault: "hard"- workspace_id string | null
Scope the budget to this client workspace: it binds only requests from that workspace's keys. Omitted or null: the whole organisation. Both may exist for one agent and interval.
Responses
- agent string
- interval string
- limit_usd number
- include_byok boolean
- mode enum
- One of: hard, soft
- workspace_id string | null
Remove an agent budget
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- agent string · pathrequired
The X-Autonomous-Relay-Agent value.
- interval string · pathrequired
The window.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.- workspace_id string · query
Remove the budget scoped to this client workspace. Absent: the organisation-wide one.
Responses
- deleted anyrequired
Guardrails
Policy: allowlists, budgets, privacy and content filters.
Get the account routing defaults
The default model, fallback models and default provider sort for every key in the organisation. Any role may read this.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- default_model string | nullrequired
- fallback_models string[]required
- default_sort enumrequired
- One of: price, throughput, latency, null
- lock_sort booleanrequired
- updated_at string | nullrequired
Set the account routing defaults
Replaces the whole set; an omitted field is cleared. Owner and Admin only (org:write).
default_model is used when a request names no model (otherwise a 400). fallback_models are tried, in order, after the models a request names, within the same depth of three a request's own models chain gets. default_sort applies when a request sets no provider.sort; with lock_sort, a request's own sort is ignored. None of these widen what a key may reach: every model still passes guardrails, the privacy policy and BYOK. Every model must be a listed, ready model id.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Request body
- default_model string | null
A listed model id, used when a request names none.
- fallback_models string[]
- default_sort enum
The provider sort when a request sets none.
One of: price, throughput, latency, null- lock_sort boolean
Ignore a request's own provider.sort. Needs default_sort.
Responses
- default_model string | nullrequired
- fallback_models string[]required
- default_sort enumrequired
- One of: price, throughput, latency, null
- lock_sort booleanrequired
- updated_at string | nullrequired
Get the IP allowlist
§10.3. The CIDR ranges every key in the organisation must call from, and the address the gateway sees for this request. Empty is off. Any role may read this.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- cidrs string[]required
- your_address stringrequired
This request's address, as the allowlist is checked against it.
Set the IP allowlist
Replaces the list. Owner and Admin only (org:write). Up to 100 ranges, IPv4 or IPv6; a bare address is a single host, and an address with host bits set past its prefix (10.0.0.1/8) is refused as a likely typo. [] turns the allowlist off.
While the list is not empty, every key of the organisation — inference and management, Authorization or x-api-key, and dashboard sessions — is refused from any other address with 403 `ip_not_allowed`, naming the address. A list that does not include the address saving it is a 400, so a change can never lock out the key making it. Takes effect at once on the instance serving the call and within 10 seconds everywhere else.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Request body
- cidrs string[]required
CIDR ranges, e.g.
203.0.113.0/24or2001:db8::/32.
Responses
- cidrs string[]required
- your_address stringrequired
Get the account privacy policy
The account level of the org → workspace → key chain (§4.2, §10.3), with the eligibility preview for it and the regions endpoints declare. Any role may read this.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- policy PrivacyPolicy
- eligibility Eligibility
- regions string[]
Set the account privacy policy
Replaces the whole policy; an omitted field is off. Owner and Admin only (org:write). It can only tighten routing for every key in the organisation: regions intersects with guardrails' allowed_data_regions, and an endpoint that declares no region fails it. zdr, zdr_groups and deny_training were removed: we do not record providers' retention or training terms, which are set by your own agreement with the provider. They are accepted switched off and refused switched on. Unknown fields are a 400.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Request body
- zdr boolean
Removed.
falseis accepted;trueis a 400.- zdr_groups string[]
Removed. An empty list is accepted; any group is a 400.
- deny_training boolean
Removed.
falseis accepted;trueis a 400.- regions string[]
Responses
- policy PrivacyPolicy
- eligibility Eligibility
Preview a privacy policy before saving it
How many models stay available under the policy in the body, and which do not and why. Nothing is saved. Policy only: BYOK credentials and guardrails narrow further per key.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Request body
- zdr boolean
Removed.
falseis accepted;trueis a 400.- zdr_groups string[]
Removed. An empty list is accepted; any group is a 400.
- deny_training boolean
Removed.
falseis accepted;trueis a 400.- regions string[]
Responses
- available integerrequired
- unavailable integerrequired
- excluded object[]required
Get input/output logging settings
§13.1. An organisation that has never configured this gets the defaults: off, 90-day retention, consented to self_access only.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- enabled booleanrequired
§13.1: off by default. Cannot be set true in this release — gated on the review of
PIA-2026-001.- key_include string[]required
Key hashes to capture. Empty means every key.
- key_exclude string[]required
Exclusion wins over inclusion — a key in both is not captured.
- retention_days integerrequired
At least 90 (§13.1's ~3-month floor). Content past this is deleted hourly.
- locked booleanrequired
Settings frozen; further changes refused until cleared.
- purposes enum[]required
What this organisation consented to.
self_accessis its own replay and debugging;ragwould be indexing, and is a separate grant because consent is purpose-specific.- consented_at string | null
When logging was enabled. Null while it is off.
Configure input/output logging
Management key only: an inference key must not be able to change what is recorded about its own traffic.
`enabled: true` is refused in this release. It is gated on the review of PIA-2026-001, whose adequacy conclusion depends on prompt content not being stored. Every other field configures now.
locked: true freezes the settings; further changes are refused until it is cleared — and changing the setting needs the Owner or Developer role (a management key with no person behind it has full power).
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- enabled boolean
Refused when true in this release.
- key_include string[]
Key hashes to capture. Empty means every key.
- key_exclude string[]
Exclusion wins over inclusion — a key in both is not captured.
- retention_days integer
§13.1's ~3-month floor.
- locked boolean
- purposes enum[]
What the organisation consents to. Must include
self_access; to stop storing, disable logging instead. Consent is purpose-specific — agreeing that we store your prompts so you can replay them is not agreeing that we may index them.
Responses
- enabled booleanrequired
§13.1: off by default. Cannot be set true in this release — gated on the review of
PIA-2026-001.- key_include string[]required
Key hashes to capture. Empty means every key.
- key_exclude string[]required
Exclusion wins over inclusion — a key in both is not captured.
- retention_days integerrequired
At least 90 (§13.1's ~3-month floor). Content past this is deleted hourly.
- locked booleanrequired
Settings frozen; further changes refused until cleared.
- purposes enum[]required
What this organisation consented to.
self_accessis its own replay and debugging;ragwould be indexing, and is a separate grant because consent is purpose-specific.- consented_at string | null
When logging was enabled. Null while it is off.
List guardrails
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
- name string
- model_allowlist string[]
- provider_allowlist string[]
- allowed_data_regions string[]
Regions an endpoint may run in, matched exactly against the endpoint
deployment_regionfield and lower-cased on write. Empty is unrestricted. This fails CLOSED: an endpoint that declares no region is not in one, so it is refused. A region no ready endpoint declares is rejected at write time rather than refusing every request later.- budget_nanodollars string | null
Nanodollars (1e-9 USD), an integer as a string.
- budget_reset string | null
- include_byok_spend boolean
Count spend made on your own provider credential toward this ceiling, at IMPUTED LIST PRICE -- what the call would have cost on platform capacity, not the platform fee charged. Defaults to true: every model is BYOK-only, so a ceiling that skipped this spend would count nothing and could never bind. Set false to count only platform spend.
- content_filter_builtins string[]
- content_filters ContentFilter[]
- filter_allowlist string[]
- created_at string
- assignments object[]
Create a guardrail
Assign it to a key to take effect. Policy merges organization, then workspace, then key, and each level can only narrow what the one above allows (§4.2).
Needs the Pro ($29/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- name stringrequired
- limit_usd number
A budget in USD, evaluated per key.
- reset_interval enum
- One of: daily, weekly, monthly, lifetime
- allowed_models string[]
- allowed_providers string[]
- allowed_data_regions string[]
Regions an endpoint may run in, matched exactly against the endpoint
deployment_regionfield and lower-cased on write. Empty is unrestricted. This fails CLOSED: an endpoint that declares no region is not in one, so it is refused. A region no ready endpoint declares is rejected at write time rather than refusing every request later.- include_byok_in_budgets boolean
Count spend made on your own provider credential toward this ceiling, at IMPUTED LIST PRICE -- what the call would have cost on platform capacity, not the platform fee charged. Defaults to true: every model is BYOK-only, so a ceiling that skipped this spend would count nothing and could never bind. Set false to count only platform spend.
- enforce_zdr object
Removed. An object of
falseis accepted; anytrueis a 400.- content_filter_builtins enum[]
- content_filters ContentFilter[]
- filter_allowlist string[]
Phrases a filter must never act on.
Responses
- id string
- name string
- budget_nanodollars string | null
Nanodollars (1e-9 USD), an integer as a string.
- budget_reset string | null
- content_filter_builtins string[]
- content_filters ContentFilter[]
- filter_allowlist string[]
Get the organisation-wide PII redaction
The built-in detectors redacted from every request the organisation makes, on every plan. Any role may read this.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- builtins string[]required
- updated_at string | nullrequired
Set the organisation-wide PII redaction
Every plan, Solo included. Replaces the list; [] turns it off. Owner and Admin only (org:write). Built-in detectors only, and redact mode only: each match is replaced by its label ([email], [SECRET:openai-key]) before routing, for every key in the organisation. It merges with the key's guardrails by union, so a guardrail can add detectors, custom patterns or block mode, never remove these. Custom patterns, block mode and per-workspace or per-key policies are guardrails (Team plan): asking for them here is a 402 subscription_required on Solo and a 400 on Team.
Needs the Pro ($29/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- builtins enum[]required
- action enum
Optional; redaction is the only action at this level.
One of: redact
Responses
- builtins string[]required
- updated_at string | nullrequired
Delete a guardrail
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
A guardrail
id.- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- deleted anyrequired
Assign a guardrail
Needs the Pro ($29/month) plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
A guardrail
id.- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- subject_type enumrequired
- One of: key, member
- subject_id stringrequired
For a key, its
hash.
Responses
- guardrail_id string
- subject_type string
- subject_id string
Auth
Dashboard sign-in.
The organisations I belong to
Every organisation the signed-in person has an active seat in, with their role and which one this session is in.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id string
- name string
- role string
- role_name string
- current boolean
Switch organisation
Moves the session into another organisation the person has a seat in (Set-Cookie). 404 for one they do not.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- org_id stringrequired
Responses
- org_id string
Get the current session
Authentication
Dashboard session
Responses
- expires_at string
- org_id string
- key_name string | null
- user object | null
- auth_method string
- super_admin boolean
This person is a super admin (Tech Service 4U staff: a verified email on a SUPER_ADMIN_DOMAINS domain, Owner or Admin of the platform organisation, signed in to the dashboard).
- org_suspended object | null
Set while a super admin has suspended this organisation: every request is refused with 403
org_suspended.
Exchange a management key for a dashboard session
Sets the httpOnly ar_session cookie and the script-readable ar_csrf cookie. Rate limited per client address.
Authentication
A management key, in the body as `key`.
Request body
- key stringrequired
A management key.
Responses
- expires_at string
- org_id string
- key_name string | null
- user object | null
- auth_method string
- super_admin boolean
This person is a super admin (Tech Service 4U staff: a verified email on a SUPER_ADMIN_DOMAINS domain, Owner or Admin of the platform organisation, signed in to the dashboard).
- org_suspended object | null
Set while a super admin has suspended this organisation: every request is refused with 403
org_suspended.
Sign out
Always succeeds, and clears both cookies.
Authentication
Dashboard session
Responses
- ended anyrequired
Describe an OAuth PKCE authorization request
What the consent screen at /auth renders. Public and rate limited: it validates the query string and echoes back the terms a key issued under it would carry. It reads nothing about any account, so a malformed request is refused before the user is asked to sign in.
Authentication
None: this endpoint is public.
Parameters
- callback_url string · query
Where to return the code. Omit for the headless flow, which then requires
S256andkey_label.httpsonly, except on localhost.- code_challenge string · query
The PKCE challenge, 43-128 characters.
- code_challenge_method enum · query
Must be
S256, sent explicitly.plainandnoneare refused for every flow, redirect included: a code returned to a localhost callback can be read by any process on that machine, and only a hashed challenge keeps it from minting a key there (RFC 7636 §7.2).- key_label string · query
Names the issued key on the Keys screen. Defaults to the callback host.
Responses
- callback_url string | nullrequired
Where the code will be returned. Null for the headless flow.
- host string | nullrequired
The callback's host — what the consent screen puts in front of the user. Null when headless, and then
key_labelis the only name there is.- headless booleanrequired
No callback URL: the code is displayed for manual entry. Requires
S256andkey_label.- key_label stringrequired
Names the issued key on the Keys screen, so access can be revoked by app.
- code_challenge_method enumrequired
Always
S256;plainandnoneare refused for every flow.One of: S256- limit numberrequired
The spend ceiling the issued key will carry. Served rather than hardcoded in the consent screen, so the terms shown are the terms applied.
- expires_in_days integerrequired
How long the issued key will last.
Approve an app and mint a one-time code
Called by the consent screen once the user agrees. The request is re-validated from the body: the preceding GET is a convenience and proves nothing about this call. Codes are single-use and expire in ten minutes.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- callback_url string
- code_challenge string
- code_challenge_method enum
- One of: S256, plain, none
- key_label string
Responses
- code stringrequired
The one-time code. Ten minutes, single use.
- redirect_to string | nullrequired
The callback URL with
codeappended, preserving any query the app already put there. Null when headless.- expires_at stringrequired
Exchange a PKCE code for an API key
Unauthenticated by design -- the caller is an app that has no key yet, and the code plus its verifier are the credential. This is the one route that answers cross-origin (Access-Control-Allow-Origin: *), because a single-page app is exactly the public client PKCE exists for. Access-Control-Allow-Credentials is never set, so no cookie can ride along.
The code is consumed the moment it is looked up, including when verification then fails: a caller gets one attempt at the verifier, not a grinding window (RFC 6749 §4.1.2). The issued key is an inference key carrying a spend ceiling and an expiry, and is revocable from the Keys screen like any other.
Authentication
The one-time authorization code and its PKCE verifier, in the body.
Request body
- code stringrequired
The code from the callback, or pasted from the headless flow.
- code_verifier string
The PKCE verifier. Required unless the code was issued under
none.- code_challenge_method enum
Optional. If sent it must MATCH the method the code was issued under; it never replaces it.
One of: S256, plain, none
Responses
- key stringrequired
The inference key. In this response and never again — only a salted hash is stored.
- hash stringrequired
Identifies the key for revocation.
- label stringrequired
The app this key was issued to.
- limit number | nullrequired
The spend ceiling, in US dollars.
- expires_at stringrequired
Our SAML service provider metadata
Public. Import it into your identity provider, or copy the entity ID and ACS URL from it.
Authentication
None: this endpoint is public.
Responses
SAML Assertion Consumer Service
Where your identity provider posts the SAMLResponse (HTTP-POST binding, form-encoded) with the RelayState. The Assertion must be signed by a certificate from your metadata, issued by your entity ID, for our entity ID, within its validity window, and answer the AuthnRequest this browser started (once; the ar_saml cookie must match the RelayState). Then as the OIDC callback: the email must be at a verified domain, and a first sign-in creates a Developer seat limited to workspaces.
Authentication
The SAML Assertion, signed by a certificate from the organisation's IdP metadata.
Responses
Does this email sign in with SSO?
Public and rate-limited. True when the address's domain is verified by an organisation with an active connection.
Authentication
None: this endpoint is public.
Request body
- email stringrequired
Responses
- sso boolean
Start signing in with SSO
A browser navigation: redirects to your identity provider with PKCE, a nonce and a state cookie (ar_sso, ten minutes).
Authentication
None: this endpoint is public.
Parameters
- email string · queryrequired
The work email; its domain picks the connection.
Responses
SSO callback
Where your identity provider sends the browser back. The ID token's issuer, audience, expiry and nonce are checked, and the email must be at one of your verified domains. A first sign-in creates a Developer seat limited to workspaces. Errors redirect to /signin?error= sso_failed, sso_domain, seat_removed, state_mismatch, expired, cancelled or sso_unknown.
Authentication
The `state` matched to the flow cookie, and an ID token from the organisation's identity provider.
Responses
List the sign-in methods this deployment offers
Authentication
None: this endpoint is public.
Responses
- management_key any
- oauth enum[]
- wallet boolean
- sso boolean
True once any organisation on this deployment has an active SSO connection: the sign-in page then offers "Sign in with SSO".
Start signing in with Google or GitHub
A browser navigation, not an API call: redirects to the provider with PKCE and a state cookie (ar_oauth, ten minutes).
Authentication
None: this endpoint is public.
Parameters
- provider enum · pathrequired
The identity provider.
Responses
The OAuth redirect target
Always redirects: to /workspace with a session on success (?welcome=1 for a new user), otherwise to /signin?error= with one of cancelled, provider_error, expired, state_mismatch, no_code, not_configured, exchange_failed.
Authentication
The `state` matched to the `ar_oauth` cookie, and the provider's authorization code.
Parameters
- provider enum · pathrequired
The identity provider.
- code string · query
The authorization code.
- state string · query
Must match the
ar_oauthcookie.- error string · query
Set by the provider when sign-in did not happen.
Responses
Start signing in with a wallet
Returns a Sign-In with Ethereum message to sign. The challenge lasts five minutes.
Authentication
None: this endpoint is public.
Request body
- address stringrequired
Responses
- message string
- nonce string
- expires_at string
Finish signing in with a wallet
Sets the session cookies on success.
Authentication
A wallet signature over a single-use nonce from POST /v1/auth/wallet/nonce.
Request body
- address stringrequired
- signature stringrequired
- nonce stringrequired
Responses
- expires_at string
- org_id string
- is_new_user boolean
SCIM
Directory sync (SCIM 2.0): your Okta or Microsoft Entra ID directory creates and deactivates people, and its groups decide which workspaces they see. Business plan or above. The /v1/scim/v2 routes take the SCIM token from Settings, not a management key. The step-by-step guide is at /docs/scim.
SCIM service provider configuration
PATCH and eq filters are supported; bulk, sort and etags are not.
Authentication
SCIM token
Responses
SCIM resource types
User and Group.
Authentication
SCIM token
Responses
List provisioned users
Filter with userName eq "..." or externalId eq "..."; startIndex and count (at most 200) page.
Authentication
SCIM token
Responses
Provision a user
userName must be a work email at one of the organisation's verified SSO domains. A new seat is a Developer limited to workspaces; an existing account at that address is reused.
Authentication
SCIM token
Responses
Get a provisioned user
One user.
Authentication
SCIM token
Parameters
- id string · pathrequired
The SCIM resource id.
Responses
Replace a user
active: false deactivates the seat.
Authentication
SCIM token
Parameters
- id string · pathrequired
The SCIM resource id.
Responses
Update a user
PatchOp. active false (or "False") deactivates the seat: it ends, the person's dashboard sessions end, and API keys they created keep working and are flagged on GET /v1/keys (creator_deactivated). active: true does not reactivate a deactivated seat; an owner re-invites.
Authentication
SCIM token
Parameters
- id string · pathrequired
The SCIM resource id.
Responses
Deprovision a user
The seat is deactivated as for active: false, and the person leaves every directory group.
Authentication
SCIM token
Parameters
- id string · pathrequired
The SCIM resource id.
Responses
List directory groups
Filter with displayName eq "..."; excludedAttributes=members omits the members.
Authentication
SCIM token
Responses
Create a directory group
Only provisioned users can be members.
Authentication
SCIM token
Responses
Get a directory group
One group and its members.
Authentication
SCIM token
Parameters
- id string · pathrequired
The SCIM resource id.
Responses
Replace a directory group
Its name and its whole member list.
Authentication
SCIM token
Parameters
- id string · pathrequired
The SCIM resource id.
Responses
Update a directory group
add / remove / replace members (also members[value eq "id"]), or replace displayName. Workspace roles follow at once.
Authentication
SCIM token
Parameters
- id string · pathrequired
The SCIM resource id.
Responses
Delete a directory group
Its members lose the workspace roles it gave them.
Authentication
SCIM token
Parameters
- id string · pathrequired
The SCIM resource id.
Responses
Directory sync settings
The SCIM base URL, the token (prefix and dates only), how many people are provisioned, and each directory group with its workspace mappings. Owner.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- base_url string
The SCIM base URL to give your directory.
- token object | null
{ prefix, created_at, last_used_at }; the token itself is shown once, astoken_valuewhen created.- users integer
- groups object[]
Create or rotate the SCIM token
Returns token_value once; it replaces any previous token at once. Business plan or above; Owner.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- base_url string
The SCIM base URL to give your directory.
- token object | null
{ prefix, created_at, last_used_at }; the token itself is shown once, astoken_valuewhen created.- users integer
- groups object[]
Stop directory sync
The token stops working. Provisioned people keep their seats. Not plan-gated.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- base_url string
The SCIM base URL to give your directory.
- token object | null
{ prefix, created_at, last_used_at }; the token itself is shown once, astoken_valuewhen created.- users integer
- groups object[]
Map a directory group to a workspace
Members of the group get this role in the workspace; across several groups the highest role wins. Workspace roles only: a directory never grants an organisation role. Memberships set by hand are not changed. Business plan or above; Owner.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The directory group id.
- workspaceId string · pathrequired
The workspace id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- role enumrequired
- One of: admin, member
Responses
- base_url string
The SCIM base URL to give your directory.
- token object | null
{ prefix, created_at, last_used_at }; the token itself is shown once, astoken_valuewhen created.- users integer
- groups object[]
Remove a group mapping
Members lose the role it gave them in that workspace.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The directory group id.
- workspaceId string · pathrequired
The workspace id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- base_url string
The SCIM base URL to give your directory.
- token object | null
{ prefix, created_at, last_used_at }; the token itself is shown once, astoken_valuewhen created.- users integer
- groups object[]
Federation
Workload identity federation: a workload exchanges the identity token its platform already gives it for a short-lived inference token, so no long-lived key is stored next to it. Policies are Owner or Admin, on every plan. The step-by-step guide is at /docs/federation.
Exchange a workload identity token for an inference token
RFC 8693 token exchange (§16.3). Public: the subject token is the credential. Send the identity token your platform gives the workload -- a GitHub Actions OIDC token, a cloud workload identity, a Kubernetes service-account token -- with the id of the federation policy it should match. The token must be signed RS256 or ES256 by the policy's issuer (checked against the issuer's published keys), unexpired, with iss, sub and aud exactly the policy's and every claim check holding. The answer is a Bearer token scoped inference, valid for at most 900 seconds and never past the subject token's own exp, accepted wherever an inference key is and acting as the key the policy names: its limit, workspace, IP allowlist and pause apply, and revoking the key ends the token. Form-encoded or JSON; body at most 32 KB, subject token at most 16 KB. Errors are RFC 6749 bodies (error, error_description).
Authentication
The workload's signed identity token, in the body as `subject_token`, checked against the federation policy.
Responses
- access_token stringrequired
- issued_token_type enumrequired
- One of: urn:ietf:params:oauth:token-type:access_token
- token_type enumrequired
- One of: Bearer
- expires_in integerrequired
- scope enumrequired
- One of: inference
The keys our access tokens are signed with
Public. A JWK Set of ES256 public keys: the current signing key and, during a rotation, the previous one. Empty when federation is not enabled. Cacheable for five minutes.
Authentication
None: this endpoint is public.
Responses
- keys object[]required
List federation policies
Owner or Admin. enabled says whether this deployment can issue tokens at all.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- id stringrequired
- name stringrequired
- issuer_url stringrequired
- subject stringrequired
- audience stringrequired
- acts_as_key_hash stringrequired
The inference key an exchanged token acts as.
- claim_checks objectrequired
- status enumrequired
- One of: active, paused
- last_used_at string | null
- created_at string
- updated_at string
Create a federation policy
Which workload tokens are accepted (issuer_url, subject, audience, claim_checks) and the inference key the exchanged token acts as (acts_as_key_hash, an active inference key of this organisation). The issuer must be a public https URL serving an OIDC discovery document with a jwks_uri. claim_checks: up to 20 {"claim": expected}; a string, number or boolean claim must equal it, an array claim must contain it. Owner or Admin.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- name stringrequired
- issuer_url stringrequired
- subject stringrequired
- audience stringrequired
- acts_as_key_hash stringrequired
- claim_checks object
Responses
- id stringrequired
- name stringrequired
- issuer_url stringrequired
- subject stringrequired
- audience stringrequired
- acts_as_key_hash stringrequired
The inference key an exchanged token acts as.
- claim_checks objectrequired
- status enumrequired
- One of: active, paused
- last_used_at string | null
- created_at string
- updated_at string
Change or pause a federation policy
Any of name, issuer_url, subject, audience, claim_checks, and status (active or paused). Pausing stops new exchanges at once; tokens already issued run out their clock (at most 900 seconds). Owner or Admin.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The policy id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- name string
- issuer_url string
- subject string
- audience string
- claim_checks object
- status enum
- One of: active, paused
Responses
- id stringrequired
- name stringrequired
- issuer_url stringrequired
- subject stringrequired
- audience stringrequired
- acts_as_key_hash stringrequired
The inference key an exchanged token acts as.
- claim_checks objectrequired
- status enumrequired
- One of: active, paused
- last_used_at string | null
- created_at string
- updated_at string
Delete a federation policy
Stops new exchanges at once; tokens already issued run out their clock (at most 900 seconds). To end those too, revoke the key the policy acts as. Owner or Admin.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The policy id.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
SSO
Single sign-on through your own identity provider, over OpenID Connect or SAML 2.0 (Okta, Microsoft Entra ID, Google Workspace, ADFS, any OIDC issuer or SAML IdP). Business plan or above; Owner or Admin. The step-by-step guide is at /docs/sso.
The single sign-on setup
The connection to your identity provider, your email domains with the TXT record each needs, and the callback URL to register. Owner or Admin.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
- callback_url string
Register this exact URL as the redirect (sign-in) URI of your OIDC app.
- saml_sp object
- connection object | null
{ protocol: oidc|saml, status: pending|active|disabled, require_sso, tested_at, created_at, issuer, client_id, saml_entity_id, saml_sso_url }; the client secret is never returned.- domains object[]
Connect your identity provider
Your OIDC app's issuer, client id and client secret. The issuer's discovery document (<issuer>/.well-known/openid-configuration) is read now and must name the same issuer. A new connection, or a changed issuer or client id, is pending (with require_sso off) until a test sign-in succeeds and it is activated again; a new secret alone keeps the connection as it is. The secret is sealed and never returned; omit it to keep the stored one. Business plan or above; Owner or Admin.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- issuer stringrequired
- client_id stringrequired
- client_secret string
Responses
- callback_url string
Register this exact URL as the redirect (sign-in) URI of your OIDC app.
- saml_sp object
- connection object | null
{ protocol: oidc|saml, status: pending|active|disabled, require_sso, tested_at, created_at, issuer, client_id, saml_entity_id, saml_sso_url }; the client secret is never returned.- domains object[]
Require single sign-on
With require_sso: true, people at your verified domains can only sign in through your identity provider; Google, GitHub and wallet sign-in and switching in from another organisation are refused for them (403 sso_required). Your Owners are exempt and keep their original method, so an identity-provider outage cannot lock you out. Turning it on ends the current dashboard sessions of the people it applies to. Needs an active connection.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- require_sso booleanrequired
Responses
- callback_url string
Register this exact URL as the redirect (sign-in) URI of your OIDC app.
- saml_sp object
- connection object | null
{ protocol: oidc|saml, status: pending|active|disabled, require_sso, tested_at, created_at, issuer, client_id, saml_entity_id, saml_sso_url }; the client secret is never returned.- domains object[]
Remove the connection
Your verified domains are kept. Not plan-gated.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- deleted boolean
Connect a SAML identity provider
Either metadata_xml (the IdP metadata file exported from Okta, Entra, Google Workspace, ADFS...) or entity_id, sso_url (HTTP-Redirect binding, https) and certificate (the signing certificate, PEM or base64). Replaces an OIDC connection. A new identity provider is pending (with require_sso off) until a test sign-in passes and it is activated again; a renewed certificate keeps the connection as it is. Assertions must be signed. Business plan or above; Owner or Admin.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- metadata_xml string
- entity_id string
- sso_url string
- certificate string
Responses
- callback_url string
Register this exact URL as the redirect (sign-in) URI of your OIDC app.
- saml_sp object
- connection object | null
{ protocol: oidc|saml, status: pending|active|disabled, require_sso, tested_at, created_at, issuer, client_id, saml_entity_id, saml_sso_url }; the client secret is never returned.- domains object[]
Activate single sign-on
Needs a successful test sign-in (GET /v1/auth/sso/test) since the connection was last changed, and at least one verified domain. Business plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- callback_url string
Register this exact URL as the redirect (sign-in) URI of your OIDC app.
- saml_sp object
- connection object | null
{ protocol: oidc|saml, status: pending|active|disabled, require_sso, tested_at, created_at, issuer, client_id, saml_entity_id, saml_sso_url }; the client secret is never returned.- domains object[]
Turn single sign-on off
Sign-in through your identity provider stops at once, and require_sso is turned off. Not plan-gated.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- callback_url string
Register this exact URL as the redirect (sign-in) URI of your OIDC app.
- saml_sp object
- connection object | null
{ protocol: oidc|saml, status: pending|active|disabled, require_sso, tested_at, created_at, issuer, client_id, saml_entity_id, saml_sso_url }; the client secret is never returned.- domains object[]
Add an email domain
Returns the TXT record to add at the domain's root (autonomousrelay-verification=<token>). At most 20 domains. Business plan or above.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Request body
- domain stringrequired
Such as acme.com.
Responses
- callback_url string
Register this exact URL as the redirect (sign-in) URI of your OIDC app.
- saml_sp object
- connection object | null
{ protocol: oidc|saml, status: pending|active|disabled, require_sso, tested_at, created_at, issuer, client_id, saml_entity_id, saml_sso_url }; the client secret is never returned.- domains object[]
Verify an email domain
Looks the TXT record up now. DNS changes can take up to an hour to be visible. A domain is verified by at most one organisation.
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- domain string · pathrequired
The domain.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- callback_url string
Register this exact URL as the redirect (sign-in) URI of your OIDC app.
- saml_sp object
- connection object | null
{ protocol: oidc|saml, status: pending|active|disabled, require_sso, tested_at, created_at, issuer, client_id, saml_entity_id, saml_sso_url }; the client secret is never returned.- domains object[]
Remove an email domain
Authentication
Management key (ar-mgmt-…) · Dashboard session
Parameters
- domain string · pathrequired
The domain.
- x-csrf-token string · header
Required with a session cookie on any method but GET: the value of the
ar_csrfcookie. Not used with a bearer key.
Responses
- callback_url string
Register this exact URL as the redirect (sign-in) URI of your OIDC app.
- saml_sp object
- connection object | null
{ protocol: oidc|saml, status: pending|active|disabled, require_sso, tested_at, created_at, issuer, client_id, saml_entity_id, saml_sso_url }; the client secret is never returned.- domains object[]
Run a test sign-in
A browser navigation from a signed-in Owner or Admin: a sign-in through your own connection, even while it is pending. It records the success (which POST /v1/sso/activate needs) and signs nobody in; the result comes back to /workspace/settings?sso_test=ok|....
Authentication
Management key (ar-mgmt-…) · Dashboard session
Responses
Runs
Agent runs (§17.1): one goal, many turns, one budget enforced across all of them.
List runs
Newest first, for the calling key's organization. An inference key, or a management key or dashboard session whose role grants usage:read.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Parameters
- limit integer · query
Page size, capped at 100.
- status enum · query
One status only.
Responses
- id stringrequired
- status enumrequired
exhaustedis set by settlement when spend reaches the budget, andpausedby the §17.4 runaway detector. A caller may set onlycompletedorcancelled— a client able to claim either of the other two could report a breach that never happened.pausedis the one non-open status that is recoverable: seePOST /v1/runs/{id}/resume.One of: open, paused, completed, exhausted, cancelled- goal string | null
- budget numberrequired
The ceiling. Required at creation, always positive: a run without one is what §17.1 exists to prevent.
- spent numberrequired
Settled. Imputed list price — what the turns were worth at catalog prices, not money billed through us. Under the BYOK-only policy inference is billed by your own provider, and a run sized on our fee would report every turn as free (§9.6).
- reserved numberrequired
Worst-case imputed cost committed by turns admitted but not yet settled. Published because
budget - spentalone overstates the headroom a run actually has.- remaining numberrequired
budget - spent - reserved.- max_turns integer | null
- turns_used integerrequired
- max_tool_calls integer | null
- tool_calls_used integerrequired
- model_policy object
- max_cost_per_minute number | null
§17.4 threshold, in USD. Null means the cost-velocity detector is off for this run.
- max_tool_calls_without_progress integer | null
§17.4 threshold. Null means the no-progress detector is off for this run.
- tool_calls_without_progress integer
Consecutive tool calls with no answering turn between them. Reset to 0 by any turn finishing with something other than
tool_calls.- pause_reason string | null
Which detector paused this run. Set only by settlement — the actionable half, since a paused run without a stated cause leaves you guessing which threshold to raise.
One of: cost_velocity, no_progress, null- paused_at string | null
- created_at string
- updated_at string
- closed_at string | null
Open a run
A run is one goal across many turns, with one budget enforced across all of them. Pass its id as run_id on each completion.
Inference class, not management: the thing that opens a run is the agent, and requiring a management key would hand every agent the credential that mints keys and moves budgets. The run is scoped to the organization, so a supervisor and its workers may hold different keys and share one.
Authentication
Inference key (ar-v1-…)
Request body
- goal string
Free text, at most 2000 characters.
- budget_usd numberrequired
Required, and positive. There is no way to open an uncapped run.
- max_turns integer
Bounds how many times the agent may ask. A failed turn refunds its money but not its turn — see
packages/docs/RUNS.md.- max_tool_calls integer
Checked at turn admission, so a single turn can exceed it by its own call count.
- model_policy object
- max_cost_per_minute_usd number
§17.4 runaway detector, opt-in. Pauses the run when spend inside a tumbling one-minute window exceeds this. Omit to leave it off.
The window is tumbling, not sliding: a burst straddling a boundary can be split across two windows and escape. Acceptable for a safety net whose job is to stop a loop running overnight; it is not a billing control.
- max_tool_calls_without_progress integer
§17.4 runaway detector, opt-in. Pauses the run after this many consecutive tool calls with no answering turn between them — "progress" meaning a turn that finished with something other than
tool_calls. Omit to leave it off.
Responses
- id stringrequired
- status enumrequired
exhaustedis set by settlement when spend reaches the budget, andpausedby the §17.4 runaway detector. A caller may set onlycompletedorcancelled— a client able to claim either of the other two could report a breach that never happened.pausedis the one non-open status that is recoverable: seePOST /v1/runs/{id}/resume.One of: open, paused, completed, exhausted, cancelled- goal string | null
- budget numberrequired
The ceiling. Required at creation, always positive: a run without one is what §17.1 exists to prevent.
- spent numberrequired
Settled. Imputed list price — what the turns were worth at catalog prices, not money billed through us. Under the BYOK-only policy inference is billed by your own provider, and a run sized on our fee would report every turn as free (§9.6).
- reserved numberrequired
Worst-case imputed cost committed by turns admitted but not yet settled. Published because
budget - spentalone overstates the headroom a run actually has.- remaining numberrequired
budget - spent - reserved.- max_turns integer | null
- turns_used integerrequired
- max_tool_calls integer | null
- tool_calls_used integerrequired
- model_policy object
- max_cost_per_minute number | null
§17.4 threshold, in USD. Null means the cost-velocity detector is off for this run.
- max_tool_calls_without_progress integer | null
§17.4 threshold. Null means the no-progress detector is off for this run.
- tool_calls_without_progress integer
Consecutive tool calls with no answering turn between them. Reset to 0 by any turn finishing with something other than
tool_calls.- pause_reason string | null
Which detector paused this run. Set only by settlement — the actionable half, since a paused run without a stated cause leaves you guessing which threshold to raise.
One of: cost_velocity, no_progress, null- paused_at string | null
- created_at string
- updated_at string
- closed_at string | null
Get a run and its tree
§17.1's tree: turns, per-turn cost, cache hit rate, failed tool calls, model switches and a terminal status. An inference key, or a management key or dashboard session whose role grants usage:read.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The run id.
Responses
Close a run
Terminal. An open or paused run closes; closing an already-closed run is a 409 naming its current status, never a silent no-op. An inference key, or a management key or dashboard session whose role grants config:write.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The run id.
Request body
- status enum
- One of: completed, cancelledDefault: "completed"
Responses
- id stringrequired
- status enumrequired
exhaustedis set by settlement when spend reaches the budget, andpausedby the §17.4 runaway detector. A caller may set onlycompletedorcancelled— a client able to claim either of the other two could report a breach that never happened.pausedis the one non-open status that is recoverable: seePOST /v1/runs/{id}/resume.One of: open, paused, completed, exhausted, cancelled- goal string | null
- budget numberrequired
The ceiling. Required at creation, always positive: a run without one is what §17.1 exists to prevent.
- spent numberrequired
Settled. Imputed list price — what the turns were worth at catalog prices, not money billed through us. Under the BYOK-only policy inference is billed by your own provider, and a run sized on our fee would report every turn as free (§9.6).
- reserved numberrequired
Worst-case imputed cost committed by turns admitted but not yet settled. Published because
budget - spentalone overstates the headroom a run actually has.- remaining numberrequired
budget - spent - reserved.- max_turns integer | null
- turns_used integerrequired
- max_tool_calls integer | null
- tool_calls_used integerrequired
- model_policy object
- max_cost_per_minute number | null
§17.4 threshold, in USD. Null means the cost-velocity detector is off for this run.
- max_tool_calls_without_progress integer | null
§17.4 threshold. Null means the no-progress detector is off for this run.
- tool_calls_without_progress integer
Consecutive tool calls with no answering turn between them. Reset to 0 by any turn finishing with something other than
tool_calls.- pause_reason string | null
Which detector paused this run. Set only by settlement — the actionable half, since a paused run without a stated cause leaves you guessing which threshold to raise.
One of: cost_velocity, no_progress, null- paused_at string | null
- created_at string
- updated_at string
- closed_at string | null
Resume a run the runaway detector paused
The counterpart to pausing rather than cancelling (§17.4): the detector stops a run so a human can look at it, and this is how they say "I looked, carry on".
Clears the counters that caused the pause — without that it would pause again on the very next settlement and this call would appear to do nothing. The budget and turn counts are deliberately not reset: those are the caps the run was opened under, and a pause is not an amnesty.
Only a paused run resumes. exhausted and cancelled are genuinely finished, and resuming those would be a way to reopen a budget that has already bound.
An inference key, or a management key or dashboard session whose role grants config:write.
Authentication
Inference key (ar-v1-…) · Management key (ar-mgmt-…) · Dashboard session
Parameters
- id string · pathrequired
The run id.
Responses
- id stringrequired
- status enumrequired
exhaustedis set by settlement when spend reaches the budget, andpausedby the §17.4 runaway detector. A caller may set onlycompletedorcancelled— a client able to claim either of the other two could report a breach that never happened.pausedis the one non-open status that is recoverable: seePOST /v1/runs/{id}/resume.One of: open, paused, completed, exhausted, cancelled- goal string | null
- budget numberrequired
The ceiling. Required at creation, always positive: a run without one is what §17.1 exists to prevent.
- spent numberrequired
Settled. Imputed list price — what the turns were worth at catalog prices, not money billed through us. Under the BYOK-only policy inference is billed by your own provider, and a run sized on our fee would report every turn as free (§9.6).
- reserved numberrequired
Worst-case imputed cost committed by turns admitted but not yet settled. Published because
budget - spentalone overstates the headroom a run actually has.- remaining numberrequired
budget - spent - reserved.- max_turns integer | null
- turns_used integerrequired
- max_tool_calls integer | null
- tool_calls_used integerrequired
- model_policy object
- max_cost_per_minute number | null
§17.4 threshold, in USD. Null means the cost-velocity detector is off for this run.
- max_tool_calls_without_progress integer | null
§17.4 threshold. Null means the no-progress detector is off for this run.
- tool_calls_without_progress integer
Consecutive tool calls with no answering turn between them. Reset to 0 by any turn finishing with something other than
tool_calls.- pause_reason string | null
Which detector paused this run. Set only by settlement — the actionable half, since a paused run without a stated cause leaves you guessing which threshold to raise.
One of: cost_velocity, no_progress, null- paused_at string | null
- created_at string
- updated_at string
- closed_at string | null
MCP
Model Context Protocol, for coding agents. Every tool adapts a route documented above.
Not offered: this server has no server-initiated stream
Always 405. MCP's transport requires that status from a server offering no SSE stream, and it is answered deliberately rather than left to a 404, because a client probing for a stream must read "not offered" rather than "wrong URL".
Authentication
None: this endpoint is public.
Responses
Call the MCP server
JSON-RPC 2.0 over MCP's Streamable HTTP transport, protocol revision 2025-06-18. Methods: initialize, tools/list, tools/call, ping, and the notifications/* messages.
Every tool is an adapter over a route documented elsewhere in this file, dispatched through this gateway's own router — so an MCP call passes the same authentication, rate limits, spend ceilings, guardrails and ledger as the HTTP call it stands for. See packages/docs/MCP.md.
Requires an inference key; a management key gets 403, as it does on /v1/chat/completions. The OAuth PKCE flow (/auth) is the intended way for a coding tool to obtain one.
Stateless: no Mcp-Session-Id, because several instances run behind a load balancer with no sticky routing. JSON-RPC batching is refused — revision 2025-06-18 removed it.
Authentication
Inference key (ar-v1-…)
Request body
- jsonrpc anyrequired
- id string | integer | null
Omit the field entirely for a notification, which is answered with 202 and no body. An explicit
nullis a request, not a notification.- method stringrequired
e.g.
tools/call.- params object
Responses
- jsonrpc anyrequired
- id string | integer | nullrequired
- result object
For
tools/call:content(an array of text blocks) andisError.- error object
The MCP Server Card
This MCP server's Server Card (SEP-2127), for discovery before connecting: its identity, the Streamable HTTP endpoint, the protocol revisions it speaks, and the Authorization header it needs. It lists no tools; tools/list does, at runtime. Served as application/mcp-server-card+json, readable from any origin, cacheable for an hour, and listed in the site's agent catalogue (/.well-known/ard.json).
Authentication
None: this endpoint is public.
Responses
Meta
Health, region, and this document.
Health
Public; for load balancers and uptime checks. A 500 means the database is unreachable.
Liveness, the version this document already publishes, and whether the rate limiter is shared across instances — nothing here varies with account activity.
Authentication
None: this endpoint is public.
Responses
- status anyrequired
- version string
The same value this document publishes as
info.version.- rate_limiting object
Receive a Content-Security-Policy violation report
For browsers, not for you: the dashboard's CSP names this path in report-uri. Accepts the legacy application/csp-report document and the Reporting API's application/reports+json array; the violation's document, directive, blocked URI and source are logged (each clipped to 200 characters, at most ten per report) and nothing is stored. Unauthenticated and rate-limited per address like the catalog.
Authentication
None: this endpoint is public.
Responses
The caller's coarse region
As the edge reported it. The dashboard uses it to choose a language, so it is never refused by region.
Authentication
None: this endpoint is public.
Responses
- region string | null
- subdivision string | null
This document, as JSON
Authentication
None: this endpoint is public.
Responses
This document, as YAML
Authentication
None: this endpoint is public.
Responses
This document, as JSON
Authentication
None: this endpoint is public.
Responses
This document, as YAML
Authentication
None: this endpoint is public.