Automatio API
One key, three products: the same tools the Automatio agent uses, an OpenAI-compatible model endpoint, and full agent runs. Billed per call against your credit balance — no provider keys to manage.
Quickstart
Create a key on the Integrations page, then make your first call. This one pulls the full transcript of a YouTube video:
curl -X POST 'https://automatio.ai/api/v1/query' \
-H 'Authorization: Bearer aut_yourkey' \
-H 'Content-Type: application/json' \
-d '{"tool":"youtube_transcript","params":{"videoId":"jNQXAC9IVRw"}}'The tool's result is returned directly — there is no response envelope to unwrap:
{
"videoId": "jNQXAC9IVRw",
"segmentCount": 6,
"wordCount": 39,
"segments": [
{ "t": 1, "ts": "0:01", "text": "All right, so here we are, in front of the elephants" },
{ "t": 5, "ts": "0:05", "text": "the cool thing about these guys is that they have really..." }
]
}Authentication
Every request takes the same bearer key, whichever endpoint you use. At creation a key can be scoped to specific tools, specific models, a lifetime credit budget, and a per-minute rate limit.
Authorization: Bearer aut_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Scope keys narrowly when you hand one to an agent or a third party. A tool allowlist is not only a safety boundary — it also shrinks what an MCP client has to load, since tools/list returns only the granted subset.
REST endpoint
POST https://automatio.ai/api/v1/query
curl -X POST 'https://automatio.ai/api/v1/query' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"tool":"web_search","params":{"query":"hello world"}}'What a call cost
Every response that ran a tool carries the credits that call billed — on REST, on MCP tools/call, and on /chat/completions. Sum what you receive and the total is exact; you never need a rate card.
{
"rows": [ ... ],
"totalRows": 12,
"automatio": { "credits_charged": 15 }
}Add a charge whenever the response has the field — not when the status is 2xx. A request rejected before the tool ran (401, 429, 400, or 402 once the key’s budget is gone) billed nothing and carries no automatio block at all. A tool that ran and then failed returns 502 (or 402) with a real charge attached, because a refusal after a partial charge is exactly when you need the number.
Prices in the tool table are per call. The metered tools — apify_actor_details, apify_run_actor, apify_search_actors, image_analyze, image_generate, reddit_post, reddit_search, video_analyze and video_generate — bill the provider’s real cost, so they list no price and this field is the only real number for them.
Credits are the exact unit, so report them as credits. If you need a dollar figure, 2,778 credits = $1 at the reference tier, also served as billing.creditsPerUsd on GET /api/v1/catalog. Plans buy credits at other rates, so a converted total is indicative rather than an account’s actual bill.
MCP server
A stateless Model Context Protocol server (Streamable HTTP) at https://automatio.ai/api/v1/mcp. Point any MCP client at it with the same bearer key and the tools appear natively in your agent — tools/list returns what the key is granted, minus any tool that cannot finish inside an MCP call. video_generate renders for minutes, so it is REST-only — call it at POST /api/v1/query. Everything else out of scope never enters the session at all.
claude mcp add --transport http automatio https://automatio.ai/api/v1/mcp \
--header "Authorization: Bearer aut_yourkey"
# or commit it to the project — .mcp.json in the repo root:
{
"mcpServers": {
"automatio": {
"type": "http",
"url": "https://automatio.ai/api/v1/mcp",
"headers": { "Authorization": "Bearer aut_yourkey" }
}
}
}The shapes genuinely differ between clients — VS Code nests under servers rather than mcpServers, opencode uses mcp with type: "remote", and Codex is TOML whose bearer_token_env_var wants the NAME of an environment variable rather than the key. A config copied from the wrong client usually fails silently — the server simply never appears.
Discovery is free. Connecting, and listing tools, costs nothing — only an actual tools/call is billed, at the same per-tool credit price as REST. The legacy SSE transport is intentionally not supported.
For coding agents that would rather read one document than negotiate a protocol, the whole API is available as Markdown in a single request at /api/v1/catalog?format=md.
AI models (OpenAI-compatible)
Call any chat model through Automatio and have the tokens billed to your credits — no provider keys to manage. Your key needs the AI models scope. The endpoint is wire-compatible with the OpenAI Chat Completions API, so the official OpenAI SDK works unchanged — just point it at Automatio.
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://automatio.ai/api/v1',
apiKey: 'aut_yourkey',
});
const res = await client.chat.completions.create({
model: 'google/gemini-3-flash',
messages: [{ role: 'user', content: 'Hello' }],
});Streaming is supported (stream: true). A key can be restricted to specific models at creation.
Tools, JSON mode and sampling. The OpenAI parameters tools and tool_choice (the model's call comes back as tool_calls; you run the function and send the result back in a tool message), response_format (json_object and json_schema), stop, seed and the two penalties are honoured. A parameter that cannot be (n above 1, logprobs, ...) is refused with a 400 that names it. Models differ in what they honour: one that was measured not to honour a parameter lists it in doesNotHonour in the catalogue, and a request that uses it is refused naming the model, instead of an answer with the setting missing. A reply may carry automatio.warnings when the model reports ignoring a setting, and for temperature and top_p on a model that does not apply them (listed in doesNotApply in the catalogue, for example the Claude 5 and GPT-5 models): those are sent and answered rather than refused, because most clients send a default temperature. strict on a tool is accepted; the arguments are the model's own, not enforced against the schema.
Images (vision)
Models marked vision below accept image input — captioning, OCR, reading a screenshot or a chart. Send it exactly the way the OpenAI API does, as a content array with an image_url part (an https URL or a data: URI). Images are accepted only on user messages; sending one to a text-only model returns 400 naming the models that do accept them.
const res = await client.chat.completions.create({
model: 'zai/glm-4.6v-flash',
messages: [{
role: 'user',
content: [
{ type: 'text', text: 'Caption this image.' },
{ type: 'image_url', image_url: { url: 'https://example.com/photo.jpg' } },
],
}],
});For a one-call version that picks the model for you, the image_analyze tool does the same job through /api/v1/query and MCP.
Video and PDF files
Models marked video watch a clip, motion and audio included: send a video_url part with a public link to an .mp4, .webm or .mov, up to 10 minutes and 2 per request. Models marked file read a PDF in a file part, as a base64 data: URI or an https link (3 per request, 20 MB inline). Both are billed from the model's real token use. A model without the flag gets a 400 naming the models that have it.
const res = await client.chat.completions.create({
model: 'google/gemini-3-flash',
messages: [{
role: 'user',
content: [
{ type: 'text', text: 'What happens in this clip, and what is said?' },
{ type: 'video_url', video_url: { url: 'https://example.com/clip.mp4' } },
],
}],
});
// A PDF, inline:
{ type: 'file', file: { file_data: 'data:application/pdf;base64,' + base64, filename: 'report.pdf' } }To read a video with any model, or without choosing one, call the video_analyze tool through /api/v1/query or MCP: a public link and a question in, text with timestamps out, up to 5 minutes, billed at the real cost plus markup.
97 models
| model | context | vision | video | file | tools | credits/1M in | credits/1M out |
|---|---|---|---|---|---|---|---|
openai/gpt-5-nano | 400,000 | yes | — | yes | yes | 167 | 1,333 |
openai/gpt-5-mini | 400,000 | yes | — | yes | yes | 833 | 6,667 |
openai/gpt-5.6-luna | 1,050,000 | yes | — | yes | yes | 667 | 4,000 |
openai/gpt-4.1-mini | 1,047,576 | yes | — | yes | yes | 1,333 | 5,334 |
openai/gpt-4.1-nano | 1,047,576 | yes | — | yes | yes | 333 | 1,333 |
google/gemini-2.5-flash | 1,000,000 | yes | yes | yes | yes | 1,000 | 8,334 |
google/gemini-3-flash | 1,000,000 | yes | yes | yes | yes | 1,667 | 10,001 |
google/gemini-3.5-flash | 1,000,000 | yes | yes | yes | yes | 5,000 | 30,002 |
google/gemini-3.6-flash | 1,000,000 | yes | yes | yes | yes | 2,500 | 12,501 |
google/gemini-3.7-flash | 1,000,000 | yes | yes | yes | yes | 2,500 | 12,501 |
minimax/minimax-m3 | 512,000 | yes | — | yes | yes | 1,000 | 4,000 |
google/gemini-4-argon | 1,000,000 | yes | yes | yes | yes | 6,667 | 33,336 |
google/gemini-4-carbon | 1,000,000 | yes | yes | yes | yes | 6,667 | 33,336 |
google/gemini-3.8-flash | 1,000,000 | yes | yes | yes | yes | 2,500 | 12,501 |
google/gemini-3.5-flash-lite | 1,000,000 | yes | yes | yes | yes | 1,000 | 8,334 |
alibaba/qwen3.7-flash | 991,000 | yes | — | — | yes | 100 | 433 |
alibaba/qwen3.8-flash | 991,000 | yes | — | — | yes | 500 | 1,567 |
alibaba/qwen3.5-flash | 1,000,000 | yes | — | — | yes | 333 | 1,333 |
alibaba/qwen3.5-plus | 1,000,000 | yes | — | — | yes | 1,333 | 8,001 |
minimax/minimax-m2 | 205,000 | — | — | — | yes | 1,000 | 4,000 |
openai/gpt-5 | 400,000 | yes | — | yes | yes | 4,167 | 33,336 |
openai/gpt-5.1-thinking | 400,000 | yes | — | yes | yes | 4,167 | 33,336 |
openai/gpt-5.6-sol | 1,050,000 | — | — | yes | yes | 13,334 | 66,672 |
openai/gpt-5.6-terra | 1,050,000 | — | — | yes | yes | 6,667 | 40,003 |
anthropic/claude-sonnet-4.5 | 1,000,000 | yes | — | yes | yes | 10,001 | 50,004 |
google/gemini-2.5-pro | 1,048,576 | yes | yes | yes | yes | 4,167 | 33,336 |
anthropic/claude-opus-4.5 | 200,000 | yes | — | yes | yes | 16,668 | 83,340 |
openai/gpt-5.2 | 400,000 | yes | — | yes | yes | 5,834 | 46,670 |
openai/gpt-5.2-pro | 400,000 | yes | — | yes | yes | 70,006 | 560,045 |
openai/gpt-5.3-codex | 400,000 | yes | — | yes | yes | 5,834 | 46,670 |
openai/gpt-5-pro | 400,000 | yes | — | yes | yes | 50,004 | 400,032 |
openai/gpt-5.5 | 1,000,000 | yes | — | yes | yes | 16,668 | 100,008 |
openai/gpt-5.5-pro | 1,000,000 | yes | — | yes | yes | 100,008 | 600,048 |
anthropic/claude-sonnet-4.6 | 1,000,000 | yes | — | yes | yes | 10,001 | 50,004 |
anthropic/claude-sonnet-5 | 1,000,000 | yes | — | yes | yes | 6,667 | 33,336 |
anthropic/claude-opus-4.6 | 1,000,000 | yes | — | yes | yes | 16,668 | 83,340 |
openai/gpt-6-astra | 1,050,000 | yes | — | yes | yes | 33,336 | 166,680 |
spacexai/grok-4.6 | 500,000 | yes | — | — | yes | 6,667 | 20,002 |
anthropic/claude-fable-5.1 | 1,000,000 | yes | — | yes | yes | 33,336 | 166,680 |
anthropic/claude-fable-5.2 | 1,000,000 | yes | — | yes | yes | 26,669 | 133,344 |
google/gemini-3.1-pro-preview | 1,000,000 | yes | yes | yes | yes | 6,667 | 40,003 |
zai/glm-5 | 202,800 | — | — | — | yes | 3,334 | 10,668 |
zai/glm-5.1 | 202,800 | — | — | — | yes | 4,667 | 14,668 |
zai/glm-5.2 | 1,000,000 | — | — | — | yes | 4,667 | 14,668 |
zai/glm-5.3 | 1,000,000 | — | — | — | yes | 4,667 | 14,668 |
deepseek/deepseek-v4.1-flash-1017 | 1,048,576 | yes | — | — | yes | 1,000 | 4,000 |
deepseek/deepseek-v4.1-flash | 1,048,576 | yes | — | — | yes | 1,000 | 4,000 |
particle/particle-1 | 1,048,576 | yes | — | — | yes | 417 | 1,667×2 peak |
inception/mercury-3 | 1,000,000 | — | — | — | yes | 333 | 1,167 |
inception/mercury-2.5 | 260,000 | — | — | — | yes | 133 | 500 |
zai/glm-5.3-flash | 1,000,000 | yes | — | — | yes | 500 | 1,667 |
alibaba/qwen3.7-max | 991,000 | — | — | — | yes | 8,334 | 25,002 |
alibaba/qwen3.8-max | 262,144 | yes | — | — | yes | 6,667 | 20,002 |
alibaba/qwen3.8-max-0902 | 991,000 | yes | — | — | yes | 6,667 | 20,002 |
mistral/mistral-large-4 | 1,048,576 | yes | — | — | yes | 2,334 | 7,001 |
alibaba/qwen3.8-27b | 262,144 | yes | yes | yes | yes | 200 | 7,334 |
xiaomi/mimo-v2.6-flash | 1,048,576 | yes | yes | — | yes | 467 | 933 |
xiaomi/mimo-v2.6-pro | 1,048,576 | yes | yes | — | yes | 1,450 | 2,900 |
spacexai/grok-4.7 | 500,000 | yes | — | — | yes | 6,667 | 20,002 |
stepfun/step-5-preview | 1,048,576 | yes | — | — | yes | 3,334 | 9,001 |
zai/glm-5.3-flashx | 1,000,000 | yes | — | — | yes | 1,233 | 4,167 |
alibaba/qwen3.8-omni-flash | 1,000,000 | yes | — | — | yes | 500 | 1,567 |
openai/gpt-6-luna | 1,050,000 | yes | — | yes | yes | 333 | 1,667 |
openai/gpt-6-sol | 1,050,000 | yes | — | yes | yes | 6,667 | 33,336 |
openai/gpt-6.1-terra | 1,050,000 | yes | — | yes | yes | 3,334 | 16,668 |
openai/gpt-6.1-sol | 1,050,000 | yes | — | yes | yes | 6,667 | 33,336 |
anthropic/claude-sonnet-5.5 | 1,000,000 | yes | — | yes | yes | 6,667 | 33,336 |
anthropic/claude-opus-5.5 | 1,000,000 | yes | — | yes | yes | 13,334 | 66,672 |
anthropic/claude-haiku-5.5 | 1,000,000 | yes | — | yes | yes | 333 | 1,667 |
anthropic/claude-haiku-4.5 | 200,000 | yes | — | yes | yes | 3,334 | 16,668 |
moonshotai/kimi-k2.5 | 256,000 | yes | yes | — | yes | 2,000 | 10,001 |
moonshotai/kimi-k2.6 | 262,000 | yes | yes | — | yes | 3,167 | 13,334 |
moonshotai/kimi-k2.7-code | 256,000 | yes | yes | — | yes | 3,167 | 13,334 |
moonshotai/kimi-k3.1-pro | 1,000,000 | yes | — | — | yes | 6,667 | 33,336 |
moonshotai/kimi-k3 | 1,000,000 | yes | yes | yes | yes | 10,001 | 50,004 |
deepseek/deepseek-v3.2 | 128,000 | — | — | — | yes | 2,067 | 6,167 |
deepseek/deepseek-v3.2-thinking | 128,000 | — | — | — | yes | 2,067 | 6,167 |
deepseek/deepseek-v4-flash-0731 | 1,000,000 | — | — | — | yes | 433 | 867 |
deepseek/deepseek-v4-flash-vision-exp | 1,048,576 | yes | — | — | yes | 733 | 2,167 |
deepseek/deepseek-v4-pro | 1,048,600 | — | — | — | yes | 4,400 | 13,201 |
deepseek/deepseek-v4-pro-0813 | 1,000,000 | — | — | — | yes | 2,200 | 6,601×2 peak |
meta/llama-3.3-70b | 128,000 | — | — | — | yes | 2,400 | 2,400 |
meta/muse-spark-1.3 | 1,048,576 | yes | — | yes | yes | 4,167 | 14,168 |
meta/muse-ember | 1,048,576 | yes | — | yes | yes | 333 | 1,667 |
meta/muse-spark-1.3-contributor | 1,048,576 | yes | — | yes | yes | 333 | 667 |
meta/muse-spark-1.2 | 1,048,576 | yes | — | yes | yes | 4,167 | 14,168 |
meta/muse-spark-1.2-contributor | 1,048,576 | yes | — | yes | yes | 333 | 667 |
inclusionai/ling-3.0-flash | 256,000 | — | — | — | yes | 67 | 200 |
zai/glm-4.6 | 200,000 | — | — | — | yes | 2,000 | 7,334 |
zai/glm-4.7 | 200,000 | — | — | — | yes | 2,000 | 7,334 |
openai/gpt-oss-120b | 131,072 | — | — | — | yes | 333 | 1,667 |
openai/gpt-oss-20b | 131,072 | — | — | — | yes | 100 | 467 |
google/gemini-3.1-flash-image | 131,072 | yes | — | yes | — | 1,667 | 10,001 |
google/gemini-3.1-flash-lite-image | 65,536 | yes | — | yes | — | 833 | 5,000 |
google/gemini-nano-banana-2.1 | 131,072 | yes | — | — | — | 5,000 | 25,002 |
google/gemini-3-pro-image | 65,536 | yes | — | yes | — | 6,667 | 40,003 |
zai/glm-4.5v | 66,000 | yes | — | — | yes | 2,000 | 6,000 |
Agent runs
Give Automatio a goal and it does the work — routing to the right agents, calling tools, running multi-step — then returns the result. Your key needs the Agent runs scope. idempotencyKey is required: a run takes real actions, so a retry must never start a second one — the same key always returns the same job.
curl -X POST https://automatio.ai/api/v1/agent \
-H "Authorization: Bearer aut_yourkey" \
-H "Content-Type: application/json" \
-d '{
"goal": "Research the top 5 AI coding tools and summarize them",
"idempotencyKey": "req-2026-07-29-001"
}'Returns 202 with a jobId. Poll it for status, result and spend (add "wait": true to block until it finishes instead):
curl https://automatio.ai/api/v1/agent/{jobId} \
-H "Authorization: Bearer aut_yourkey"
# { "status": "running" | "awaiting_input" | "completed" | "failed" | "cancelled",
# "result": "...", "creditsSpent": 126 }creditsSpent is the conversation’s cumulative spend, not what that poll cost — read it, never add it up. Summing it across polls multiplies a run’s spend by the number of times you polled. It is the one billed surface that does not report a per-call automatio.credits_charged, because the quantity is genuinely different.
Start a run with "mode": "interactive" and it can pause to ask you something. The job then reports awaiting_input along with the question, and you answer it — the same run continues, nothing is lost:
curl -X POST https://automatio.ai/api/v1/agent/{jobId}/answer \
-H "Authorization: Bearer aut_yourkey" \
-H "Content-Type: application/json" \
-d '{"approved": true, "feedback": "Keep it under 500 words"}'A run also pauses before something destructive — SQL on the live database, replacing a dataset or a live site, a destructive pod command. Then awaitingInput.kind is approval and awaitingInput.approval says what would happen. Send {"approved": true} to approve it (feedback is not used for an approval), or {"approved": false, "feedback": "..."} to reject it and tell the agent why.
Follow-ups. The start response returns a conversationId. Send it back on a later call — with a fresh idempotencyKey — and that turn runs in the same conversation, so the agent still has the earlier context. Omit it for a one-off.
curl -X POST https://automatio.ai/api/v1/agent \
-H "Authorization: Bearer aut_yourkey" \
-H "Content-Type: application/json" \
-d '{
"goal": "Now dig deeper on the third one",
"conversationId": "<the id from the first call>",
"idempotencyKey": "req-2026-07-30-002"
}'One run per conversation at a time — a follow-up sent while a run is still going returns 409, and polling always reflects the latest turn. The credit limit on the key caps the whole job — counted across every turn of a conversation, not per turn — on top of your account balance. Once a conversation has spent its ceiling, the next turn is refused with 402 before it starts, and the response tells you both creditsSpent and ceilingCredits.
Long conversations. Every turn sends the whole conversation to the model, so cost grows as one gets longer. Pass historyTurnLimit to send only the most recent N turns. Leave it off — the default — and the agent sees everything, which is what makes follow-ups work; lower it only when the task genuinely does not reach further back.
Your chats and Chrome
A key can also be given access to your own Automatio account, so a program such as Claude Code can see your chats, read them, send a message into one, instruct a canvas, or hand a task to the agent working in your own Chrome. Nothing is on by default. You choose per key under Integrations, API Keys, Automatio API, and for each power you pick Off, Ask me each time (for sending, instructing and Chrome), Only the ones I pick or All of them. For Chrome the last choice reads Automatic: it does not ask. A key set to ask can also see all your chats and canvases, so it can tell you which one it means. Whatever a key starts runs as you and spends your credits, within that key's budgets.
| Power | REST | MCP tool |
|---|---|---|
| See that chats and canvases exist (titles, dates, whether something is running) | GET /api/v1/chats, /api/v1/chats/{id}, /api/v1/canvases, /api/v1/canvases/{id} | list_chats, get_chat, list_canvases, get_canvas |
| Read what was said | GET /api/v1/chats/{id}/messages, and /api/v1/chats/{id}/messages/{messageId} for the rest of one long message | read_chat, read_message_rest |
| Send a message into a chat | POST /api/v1/chats/{id}/messages | send_message |
| Instruct or stop a canvas | POST /api/v1/canvases/{id}/messages, POST /api/v1/canvases/{id}/stop | instruct_canvas, stop_canvas |
| Hand a task to the agent in your own Chrome | POST /api/v1/browser/tasks, GET /api/v1/browser/tasks/{id} | start_browser_task, get_browser_task |
Reading, sending and instructing all need the key to see the thing first. Sending, instructing and the Chrome task also need the key to be allowed to run agents. A canvas is instructed through its own endpoint; a chat that sits on a canvas cannot be sent into.
Send a message
idempotencyKey is required (8 to 80 letters, digits, dots, dashes, underscores or colons): repeating it is the same message, never a second one. The text is at most 25,000 characters, and characters nobody can see are removed from it before you are asked to approve it. The answer is 202 either way; the run takes minutes, and the reply is read from the chat afterwards. The run has only the tools the answer lists in tools: by default research and your documents, or the list you gave the key. A key cannot be given the tools that edit a project's files or deploy it, so for a code change the instruction is given in the chat itself.
curl -X POST https://automatio.ai/api/v1/chats/{chatId}/messages \
-H "Authorization: Bearer aut_yourkey" \
-H "Content-Type: application/json" \
-d '{ "text": "Summarise today and list what is left.", "idempotencyKey": "send-2026-11-06-001" }'
# The key may send here:
# { "status": "started", "runId": "...", "executionId": "..." }
# The key is set to Ask me each time (nothing is sent until you say yes):
# { "status": "pending", "id": "...", "expiresAt": "..." }A pending answer means you were asked, in the app and in a notification. Poll GET /api/v1/requests/{id} (the check_request tool) every few seconds. It reads pending until you answer, then allowed for a moment, then started, denied, expired (ten minutes pass without an answer), failed (allowed, but it could not start) or cancelled (the key was revoked first). Only the key that asked can read the answer.
A chat that is busy answers 409: wait for the run to end, or for your own answer to a question it asked, and send again with a new idempotencyKey.
Instruct a canvas
POST /api/v1/canvases/{id}/messages takes the same body and gives the canvas's master chat an instruction. It answers started with the canvasId, chatId and runId, or pending as above. The master then starts its workers with your tools and connected accounts, and everything it starts spends your credits up to the key's per-run budget, counted over the whole canvas. Follow the work with GET /api/v1/canvases/{id}, which shows each node's state. POST …/stop takes no body, asks nothing and is safe to repeat: a key that was given the canvas stops all of its work, a key that may only ask stops the work its own instructions started. A team's canvas is never reachable.
A task in your Chrome
POST /api/v1/browser/tasks takes task (a refusal names the length limit), an optional startUrl and an idempotencyKey. The agent works in your own signed-in Chrome through the Automatio extension, so remote control must be switched on there and the extension must be a recent version; otherwise the task is refused with 409 (chrome_not_connected or extension_too_old). A key set to Ask me each time shows you the words and waits for you (pending, then result.chatId on the request is the task id); a key set to Automatic starts at once with taskId. startUrl must be an http or https address, and a key can start only a limited number of tasks an hour. Poll GET /api/v1/browser/tasks/{taskId} for running, awaiting_input, completed, failed or cancelled, the agent's answer (a long one is cut; the whole of it is in your chat) and what it spent. Only the key that started a task can read it.
What stays closed
Whatever the key was given, it never reaches a hidden or temporary chat, an API job, a chat-app conversation or a team's canvas; those answer 404, the same as a chat that does not exist, and a list leaves them out. It can neither read nor send into a chat that used your Google data (403, with the reason), and a chat that other people can write to cannot be sent into. A transcript read shows text turns and one line for each tool call, never a tool's result, redacted, and another person's words in a shared chat come back withheld. List endpoints take limit and cursor. Chats also take q (a title contains this text) and canvasId.
Errors
Failures return a JSON body with an error string and a machine-readable code (insufficient_credits, upstream_error). Over MCP the same conditions come back as a tool result with isError: true rather than a transport-level failure.
| Status | Meaning |
|---|---|
| 202 | Agent run accepted — poll the job for the result |
| 400 | Unknown tool/model or malformed body |
| 401 | Missing or invalid API key |
| 402 | Out of credits, or the key's budget is exhausted |
| 403 | Tool, model or scope not granted to this key |
| 404 | A chat, canvas or task this key was not given, or that does not exist |
| 409 | Agent job is not awaiting input, or already finished; or a chat or canvas is busy with a run, or Chrome is not connected |
| 429 | Rate limit exceeded (see Retry-After header) |
| 502 | Upstream model call failed |
Tools
34 tools, callable over REST and MCP. Prices are per successful call.
Looking for worked examples and the limits of a specific endpoint? Each one has its own guide under API guides.