{"openapi":"3.1.0","info":{"title":"Superbot API","version":"2026-09-23","description":"Call models through one OpenAI- and Anthropic-compatible gateway, and manage the account behind it: scoped caller keys, custom endpoints, usage and spend, teams and devices. Errors share one envelope (`error`, `message`, `doc_url`, `request_id`); lists page with `limit`, `after_id` and `before_id`.","contact":{"name":"Superbot developers","url":"https://superbot.gg/developers"}},"servers":[{"url":"https://superbot.gg"}],"tags":[{"name":"Gateway","description":"OpenAI- and Anthropic-shaped model calls, answered in the dialect you dialed."},{"name":"Usage & spend","description":"What your keys and account spent: per request, per day, bucketed and across apps."},{"name":"Keys","description":"Mint, list, edit and revoke scoped caller keys."},{"name":"Endpoints","description":"Custom OpenAI- or Anthropic-compatible endpoints and @mention aliases."},{"name":"Teams","description":"Teams, their members and their invites."},{"name":"Devices","description":"The devices paired to your account."},{"name":"Runs","description":"Cloud agent runs: start one on a project, follow its events, cancel it, and get a signed webhook when it settles."}],"components":{"securitySchemes":{"callerKey":{"type":"http","scheme":"bearer","bearerFormat":"sbc_","description":"A caller key sent as `Authorization: Bearer sbc_…`. What it may do is its scopes."},"apiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key","description":"The same caller key sent as `x-api-key: sbc_…` (the Anthropic client default)."},"session":{"type":"http","scheme":"bearer","description":"A signed-in session or paired-device token. Not narrowed by scopes."}},"responses":{"BadRequest":{"description":"The request is malformed or a parameter is invalid; `param` names the field.","headers":{"x-request-id":{"description":"Echoes the request id the body carries (an incoming x-request-id is kept).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The bearer is missing, malformed or unknown.","headers":{"x-request-id":{"description":"Echoes the request id the body carries (an incoming x-request-id is kept).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a scope (insufficient_scope), is revoked, or may not call this route.","headers":{"x-request-id":{"description":"Echoes the request id the body carries (an incoming x-request-id is kept).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource on this account.","headers":{"x-request-id":{"description":"Echoes the request id the body carries (an incoming x-request-id is kept).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"The resource is not in a state that allows this change.","headers":{"x-request-id":{"description":"Echoes the request id the body carries (an incoming x-request-id is kept).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Over the per-key request bucket; retry after x-ratelimit-reset.","headers":{"x-request-id":{"description":"Echoes the request id the body carries (an incoming x-request-id is kept).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"GatewayError":{"description":"A gateway refusal, in the dialect you dialed; a missing scope answers the shared Error.","oneOf":[{"$ref":"#/components/schemas/OpenAIError"},{"$ref":"#/components/schemas/AnthropicError"},{"$ref":"#/components/schemas/Error"}]},"Error":{"type":"object","properties":{"error":{"type":"string","description":"Stable machine code, e.g. `insufficient_scope`.","example":"insufficient_scope"},"message":{"type":"string","description":"Human-readable explanation."},"doc_url":{"type":"string","format":"uri","description":"The developer page anchor for this code."},"request_id":{"type":"string","description":"Echoed on the `x-request-id` response header.","example":"req_5f1c0a9e2b7d4c3a1e0f9b8d"},"param":{"type":"string","description":"The request field the error is about, when there is one."}},"required":["error","message","doc_url","request_id"],"additionalProperties":{},"description":"Every refusal: the legacy `error` code plus message, doc_url and request_id."},"Scope":{"type":"string","enum":["gateway:invoke","usage:read","billing:read","keys:read","keys:write","endpoints:read","endpoints:write","teams:read","teams:write","devices:read","devices:write","runs:read","runs:write","mcp:invoke","turns:read","tools:invoke"],"description":"What a caller key may do on the account surface."},"CallerKey":{"type":"object","properties":{"id":{"type":"string","example":"ck_9f2c41d0"},"user_id":{"type":"string"},"name":{"type":"string","description":"What the tool calls itself, 1-64 chars."},"mask":{"type":"string","description":"The only form shown after mint.","example":"sbc_ab12…cd34"},"created_at":{"type":"string","format":"date-time"},"last_used_at":{"type":"string","format":"date-time"},"revoked_at":{"type":"string","format":"date-time"},"daily_limit_tokens":{"type":"number","description":"Daily spend cap in whole credits."},"monthly_limit_tokens":{"type":"number","description":"Monthly spend cap in whole credits."},"caps_unit":{"type":"string","enum":["credit"]},"allowed_models":{"type":"array","items":{"type":"string"},"description":"Glob allow-list over model names; absent = every model. With models_listed: the exact canonical ids the key may dial, and empty = none."},"models_listed":{"type":"boolean","description":"true = the listed reading: allowed_models are literal canonical ids (no globs), the key lists exactly those as its per-app picker names, and an empty list allows nothing."},"model_pins":{"type":"object","additionalProperties":{"type":"string"},"description":"Canonical model id to the stable account id it is pinned to: a pinned model dials only that account, and one id pinned to two accounts gets two picker names."},"model_aliases":{"type":"object","additionalProperties":{"type":"string"},"description":"Canonical model id (a member of allowed_models) to the custom name its picker shows: 1-64 characters of letters, numbers, dots, dashes or colons; no Cursor routing word (claude, gemini, anthropic, sonnet-, opus-, haiku-, grok, composer); not a house id (superbot, superbot-fast, superbot-omni); unique among this key's forwards; not another model's id. A refused name stores nothing. A custom name replaces the default name for that model."},"app":{"type":"string","description":"Forwarding app this listed key's model names are spelled for: cursor, copilot-cli, cline, roo, qwen-code, hermes, openclaw, zazen, default. Set at creation, cannot be changed. Absent = cursor."},"default_model":{"type":"string","description":"The model a call that names the bare house agent `superbot` (the default model of Zapier and n8n), or names no model, is answered by instead: `superbot-fast`, `superbot-omni` or a model of one of your own accounts. A call that names any other model is dialled as named. Absent = a call naming `superbot` gets `superbot`."},"route":{"type":"string","enum":["byo","credits","auto"]},"mode":{"type":"string","enum":["model","agent"]},"incognito":{"type":"boolean"},"device_id":{"type":"string"},"org_id":{"type":"string","description":"Set on a team key."},"person_id":{"type":"string","description":"Set on a key minted for a person: `per_` + 16 hex. Every key minted for the same person carries the same id. A person key has no device_id and no org_id, and is billed to the owner.","example":"per_9f2c41d0a7b35e68"},"person_name":{"type":"string","description":"The person's display name, 1-64 characters. Present on every person key."},"person_email":{"type":"string","description":"The person's email address, when the owner gave one."},"person_group":{"type":"string","description":"A free-text grouping the owner sorts people by (a team, a class), 1-64 characters."},"prompt_history":{"$ref":"#/components/schemas/PromptHistory"},"paused_at":{"type":"string","format":"date-time","description":"Set while the owner holds this person: until a PATCH clears it the key answers 403 `key_paused` at the model gateway, the `/v1/keys` routes, the relay door and the Cosmos door; every other route does not recognise a held key and answers 401 `unauthorized`. Held is not revoked. It is written to every live key of the person."},"person_limit_usd":{"type":"number","description":"The owner's monthly spend limit for this person, in US dollars to the cent. Set by the owner's `PUT /v1/keys/person/{person_id}/limit` (the Helper), written to every live key of the person, and absent while no limit is set."},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/Scope"},"description":"The EFFECTIVE scopes: stored list or the legacy set, team keys capped."}},"required":["id","user_id","name","mask","created_at","route","mode","incognito","scopes"],"additionalProperties":{}},"PromptHistory":{"type":"object","properties":{"visible_to_owner":{"type":"boolean","description":"The owner may read this person's prompts."},"retention_days":{"type":"integer","minimum":1,"maximum":3650,"description":"Whole days the prompts are kept, 1-3650."},"attested_at":{"type":"string","format":"date-time","description":"ISO 8601 time the owner attested the person was told. The owner's own claim, stored as given and not verified; the answer normalises it to UTC."}},"required":["visible_to_owner","retention_days","attested_at"],"description":"What the owner told a person about their prompts, and how long they are kept. Absent on a key until the owner sets it: the person's prompts are then not visible to the owner and follow the account's own retention."},"Upstream":{"type":"object","properties":{"slug":{"type":"string","description":"The endpoint id; `custom` for the legacy singleton."},"label":{"type":"string"},"base_url":{"type":"string"},"dialect":{"type":"string","enum":["openai","anthropic"]},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Extra header names; values are redacted for caller keys."},"models":{"type":"array","items":{"type":"string"}},"model_names":{"type":"object","additionalProperties":{"type":"string"}},"model_meta":{"type":"object","additionalProperties":{}},"probe":{"$ref":"#/components/schemas/UpstreamProbe"},"updated_at":{"type":"string"}},"required":["slug","label","base_url","dialect"],"additionalProperties":{}},"UpstreamProbe":{"type":"object","properties":{"ok":{"type":"boolean"},"models_found":{"type":"integer"},"error":{"type":"string"},"at":{"type":"string"}},"required":["ok"],"additionalProperties":{}},"Alias":{"type":"object","properties":{"token":{"type":"string","example":"@claude"},"vendor":{"type":"string"},"model_id":{"type":"string"},"label":{"type":"string"},"tier":{"type":"string"},"custody":{"type":"string"},"available":{"type":"boolean"}},"required":["token","vendor","model_id","label","tier","custody","available"]},"Model":{"type":"object","properties":{"id":{"type":"string","example":"superbot"},"object":{"type":"string","enum":["model"]},"created":{"type":"integer"},"owned_by":{"type":"string"},"lane":{"type":"string"},"tier":{"type":"string"},"available":{"type":"boolean"},"reason":{"type":"string"},"min_plan":{"type":"string"},"auto":{"type":"boolean"},"context_window":{"type":"integer"},"context_length":{"type":"integer"}},"required":["id","object","created","owned_by"],"additionalProperties":{}},"UsageGeneration":{"type":"object","properties":{"request_id":{"type":"string"},"native_tokens_prompt":{"type":"number"},"native_tokens_completion":{"type":"number"},"cache_read":{"type":"number"},"cache_write":{"type":"number"},"total_cost":{"type":"number","description":"USD at vendor list price."},"cache_discount":{"type":"number"},"is_byok":{"type":"boolean"},"model":{"type":"string"},"key_label":{"type":"string"},"session_id":{"type":"string"},"latency_ms":{"type":"number"},"ttft_ms":{"type":"number"},"status":{"type":"integer"},"ts":{"type":"string"}},"required":["native_tokens_prompt","native_tokens_completion","cache_read","cache_write","total_cost","cache_discount","is_byok","status","ts"],"description":"One request, OpenRouter generation shape."},"UsageDaily":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"days":{"type":"array","items":{"$ref":"#/components/schemas/UsageDay"}},"totals":{"type":"object","properties":{"tokens":{"type":"number"},"tokens_in":{"type":"number"},"tokens_out":{"type":"number"},"turns":{"type":"integer"},"cost_usd":{"type":"number"},"charged_usd":{"type":"number"}},"required":["tokens","tokens_in","tokens_out","turns","cost_usd","charged_usd"]}},"required":["from","to","days","totals"]},"UsageDay":{"type":"object","properties":{"day":{"type":"string","example":"2026-09-18"},"tokens":{"type":"number"},"tokens_in":{"type":"number"},"tokens_out":{"type":"number"},"cache_read":{"type":"number"},"cache_write":{"type":"number"},"turns":{"type":"integer"},"cost_usd":{"type":"number"},"charged_usd":{"type":"number"}},"required":["day","tokens","tokens_in","tokens_out","cache_read","cache_write","turns","cost_usd","charged_usd"]},"UsageBreakdown":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"tz":{"type":"string"},"bucket":{"type":"string","enum":["day","hour"]},"group":{"type":"string"},"totals":{"$ref":"#/components/schemas/UsageMetrics"},"groups":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/UsageMetrics"},{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"}},"required":["id","label"]}]}},"buckets":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/UsageMetrics"},{"type":"object","properties":{"key":{"type":"string"},"start":{"type":"string"},"by":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/UsageMetrics"}}},"required":["key","start","by"]}]}}},"required":["from","to","tz","bucket","group","totals","groups","buckets"]},"UsageMetrics":{"type":"object","properties":{"requests":{"type":"integer"},"tokens_in":{"type":"number"},"tokens_out":{"type":"number"},"cache_read":{"type":"number"},"cache_write":{"type":"number"},"tokens":{"type":"number","description":"Billed credits."},"usd":{"type":"number"},"list_usd":{"type":"number"}},"required":["requests","tokens_in","tokens_out","cache_read","cache_write","tokens","usd","list_usd"]},"Credits":{"type":"object","properties":{"credits":{"type":"object","additionalProperties":{},"description":"The pot view: beta, plan and permanent credits with a total."},"balance_credits":{"type":"number"},"balance_tokens":{"type":"number"},"total_usage_tokens":{"type":"number"},"period_usage_tokens":{"type":"number"},"capacity_tokens":{"type":"number"},"keys_count":{"type":"integer"},"paid_usd_week":{"type":"number"},"list_usd_week":{"type":"number"},"saved_usd_week":{"type":"number"},"plan":{"type":"string"},"renews_at":{"type":"string"}},"required":["credits","balance_credits","balance_tokens","total_usage_tokens","period_usage_tokens","capacity_tokens","keys_count","paid_usd_week","list_usd_week","saved_usd_week","plan"],"additionalProperties":{}},"Spend":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"currency":{"type":"string","enum":["USD"]},"total_usd":{"type":"number"},"tied_usd":{"type":"number"},"estimated_usd":{"type":"number"},"unpriced_models":{"type":"array","items":{"type":"string"}},"providers":{"type":"array","items":{"type":"object","properties":{"provider":{"type":"string"},"label":{"type":"string"},"total_usd":{"type":"number"},"usage_usd":{"type":"number"},"purchase_usd":{"type":"number"},"measured_usd":{"type":"number"},"estimated_usd":{"type":"number"},"plan_usd":{"type":"number"},"residual_usd":{"type":["number","null"]},"status":{"type":"string","enum":["caught_up","residual","estimate_only"]},"services":{"type":"array","items":{"type":"object","properties":{"service":{"type":"string"},"total_usd":{"type":"number"}},"required":["service","total_usd"]}},"unpriced_usage":{"type":"array","items":{"type":"object","properties":{"service":{"type":"string"},"sku":{"type":"string"},"quantity":{"type":"number"},"unit":{"type":"string","enum":["tokens","requests","acu","seat-month"]},"period_start":{"type":"string"},"period_end":{"type":"string"},"fresh_at":{"type":"string"}},"required":["service","sku","quantity","unit","period_start","period_end","fresh_at"]}},"sources":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"fresh_at":{"type":["string","null"]},"status":{"type":"string","enum":["ok","stale","missing"]}},"required":["source","fresh_at","status"]}}},"required":["provider","label","total_usd","usage_usd","purchase_usd","measured_usd","estimated_usd","plan_usd","residual_usd","status","services","unpriced_usage","sources"]}},"series":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string"},"providers":{"type":"object","additionalProperties":{"type":"object","properties":{"measured":{"type":"number"},"estimated":{"type":"number"},"plan":{"type":"number"}},"required":["measured","estimated","plan"]}}},"required":["day","providers"]}}},"required":["from","to","currency","total_usd","tied_usd","estimated_usd","unpriced_models","providers","series"]},"Team":{"type":"object","properties":{"id":{"type":"string","example":"org_7c1e…"},"object":{"type":"string","enum":["team"]},"name":{"type":"string"},"role":{"$ref":"#/components/schemas/TeamRole"},"member_count":{"type":"integer"},"created_at":{"type":"string"},"share_defaults":{"type":"object","properties":{"mcp":{"type":"boolean"},"rules":{"type":"boolean"},"skills":{"type":"boolean"}},"required":["mcp","rules","skills"],"description":"What a new member pools by default, per kind."},"share_policy":{"type":"string","enum":["members","editors"],"description":"Who may add items to the pool."},"require_manual_confirm":{"type":"boolean"}},"required":["id","object","name","role","member_count","created_at","share_defaults","share_policy","require_manual_confirm"],"additionalProperties":{}},"TeamRole":{"type":"string","enum":["owner","admin","editor","member"],"description":"The caller's role in this team."},"TeamMember":{"type":"object","properties":{"object":{"type":"string","enum":["team_member"]},"user_id":{"type":"string"},"role":{"$ref":"#/components/schemas/TeamRole"},"groups":{"type":"array","items":{"type":"string"}},"joined_at":{"type":"string"}},"required":["object","user_id","role","groups","joined_at"],"additionalProperties":{}},"TeamInvite":{"type":"object","properties":{"object":{"type":"string","enum":["team_invite"]},"code":{"type":"string"},"email":{"type":"string"},"role":{"$ref":"#/components/schemas/TeamRole"},"created_at":{"type":"string"},"expires_at":{"type":"string"}},"required":["object","code","email","role","created_at"],"additionalProperties":{}},"Device":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["device"]},"kind":{"type":"string"},"label":{"type":"string"},"fingerprint":{"type":"string"},"created_at":{"type":"string"},"last_seen_at":{"type":["string","null"]},"online":{"type":"boolean"},"capabilities":{"type":"object","properties":{"tools_count":{"type":"integer"},"hub_port":{"type":"integer"},"helper_version":{"type":"string"},"held_vendors":{"type":"array","items":{"type":"string"}},"held_models":{"type":"array","items":{"type":"string"}}},"required":["tools_count","held_vendors","held_models"]},"agent":{"$ref":"#/components/schemas/AgentDeviceFacet"},"key":{"type":"string","enum":["linked","not_linked","out_of_date","unknown"],"description":"Whether this device holds the account's current end-to-end encryption key, from its own last report. `linked`: it holds the current key. `not_linked`: it holds none (it can still add logins, which reach the other devices). `out_of_date`: it holds an older or a different key. `unknown`: it has not reported, or the account has no key yet. Absent on a device that holds no key (an agent computer, an API key, an MCP connector, the cloud computer, a web browser: browsers never hold the key). A desktop app reports through its Helper (`custody_via`)."},"custody_via":{"type":"string","description":"The id of the device whose key this one uses (a desktop app names its Helper); `key` is that device's state. Absent when the device holds its own."},"created_via":{"type":"string","enum":["app_link","device_code"],"description":"Present only on a Device of kind `agent_computer`. `app_link`: linked through the app-minted link, so the vendor was recorded by the app and may be shown as verified. `device_code`: the agent claimed its own vendor at a device-code approval, so show it as unverified. A missing value is `device_code`."}},"required":["id","object","kind","label","fingerprint","created_at","last_seen_at","online"]},"AgentDeviceFacet":{"type":"object","properties":{"agent_vendor":{"type":"string","enum":["grok-bot","muse","dots","manus","cursor-cloud","devin","replit","genspark","kimi","generic"],"description":"The agent VM vendor, as it declared itself at link time. `generic` is any other agent."},"tier":{"type":"string","enum":["link","data"],"description":"`link`: terminal and relay only. `data`: link plus the synced data the linking app granted."},"state":{"type":"string","enum":["online","asleep","offline"],"description":"`online`: polling now. `asleep`: suspended by its vendor (jobs wait `queued_asleep`). `offline`: not seen recently."},"expires_at":{"type":"string","description":"The next lifecycle deadline (ISO 8601), the one `expiry_kind` names. Warned 3 days ahead."},"expiry_kind":{"type":"string","enum":["data_idle","reconfirm","link_idle"],"description":"`data_idle`: 14 days idle drops the data tier to link. `reconfirm`: the 90-day re-confirm is due (missed: link tier). `link_idle`: 30 days idle unlinks it."},"reconfirm_due_at":{"type":["string","null"],"description":"When the data tier must be re-confirmed (POST /me/devices/{device_id}/agent-reconfirm); null at the link tier."}},"required":["agent_vendor","tier","state","expires_at","expiry_kind","reconfirm_due_at"],"description":"Present only on a Device of kind `agent_computer`."},"AgentJobEnqueueBody":{"type":"object","properties":{"kind":{"$ref":"#/components/schemas/AgentJobKind"},"args":{"type":"object","additionalProperties":{},"description":"The relay tool's own args, camelCase, per kind: bash {command, cwd?, timeoutMs?, runInBackground?, interactive?} (interactive: a real tty, answered with bash_write; open a terminal pane with {command: <login shell>, runInBackground: true, interactive: true}, whose result carries {type: 'terminal', terminalId}); bash_write {terminalId, input, newline?}; bash_output {terminalId, since?, wait?}; bash_kill {terminalId}; bash_resize {terminalId, cols, rows} (a terminal pane's resize of an interactive terminal's tty: integers, cols 20..500, rows 5..200; a non-interactive terminal answers not_a_tty); read {path, line?, limit?}; write {path, content, overwrite?}; glob {pattern, cwd?}; grep {pattern, path?, cwd?}. Unknown keys are refused."}},"required":["kind","args"]},"AgentJobKind":{"type":"string","enum":["bash","bash_write","bash_output","bash_kill","bash_resize","read","write","glob","grep"],"description":"The device-shell job kinds a first-party device may run on an agent computer."},"AgentJobEnqueueResponse":{"type":"object","properties":{"job_id":{"type":"string"},"state":{"$ref":"#/components/schemas/AgentJobState"},"expires_at":{"type":"string","description":"ISO 8601, 600 s after the enqueue."}},"required":["job_id","state","expires_at"]},"AgentJobState":{"type":"string","enum":["queued","queued_asleep","claimed","done","failed","expired"],"description":"`queued_asleep`: the agent computer has no open poll; the job waits for its next poll inside the 600 s TTL. `expired`: the TTL ran out before a result."},"AgentJobView":{"type":"object","properties":{"job_id":{"type":"string"},"device_id":{"type":"string"},"kind":{"$ref":"#/components/schemas/AgentJobKind"},"state":{"$ref":"#/components/schemas/AgentJobState"},"created_at":{"type":"string"},"expires_at":{"type":"string"},"result":{"$ref":"#/components/schemas/AgentJobResult"}},"required":["job_id","device_id","kind","state","created_at","expires_at"]},"AgentJobResult":{"type":"object","properties":{"ok":{"type":"boolean"},"content":{},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["ok"],"additionalProperties":{},"description":"Present once the state is `done` or `failed`."},"AgentTerminalFrame":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["output"]},"terminal_id":{"type":"string"},"seq":{"type":"integer"},"data":{"type":"string"}},"required":["type","terminal_id","seq","data"]},{"type":"object","properties":{"type":{"type":"string","enum":["exit"]},"terminal_id":{"type":"string"},"code":{"type":["integer","null"]}},"required":["type","terminal_id","code"]},{"type":"object","properties":{"type":{"type":"string","enum":["gone"]},"terminal_id":{"type":"string"}},"required":["type","terminal_id"]}],"description":"One `event: terminal` SSE frame. `output.seq` strictly increases; resume with `?since=<seq>`. The stream closes after `exit` or `gone`."},"UsageBucket":{"type":"object","properties":{"object":{"type":"string","enum":["bucket"]},"starting_at":{"type":"string","format":"date-time"},"ending_at":{"type":"string","format":"date-time"},"results":{"type":"array","items":{"$ref":"#/components/schemas/UsageResult"}}},"required":["object","starting_at","ending_at","results"]},"UsageResult":{"allOf":[{"$ref":"#/components/schemas/UsageMetrics"},{"type":"object","properties":{"api_key_id":{"type":["string","null"]},"model":{"type":["string","null"]},"lane":{"type":["string","null"]},"role":{"type":["string","null"]},"session_id":{"type":["string","null"]},"team_id":{"type":["string","null"]}}}]},"OpenAIError":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"message":{"type":"string"},"code":{"type":["string","null"]},"origin":{"type":"string","enum":["vendor"],"description":"Present, `vendor`, only when this status is your own vendor credential’s answer (also the `x-superbot-error-origin` header)."},"vendor_status":{"type":"integer","description":"With `origin`: the vendor’s own HTTP status."},"source":{"type":"string","description":"Where the problem is: `request` (your request or conversation, e.g. too long for the model), `client` (your client or tool setup, e.g. its key), `account` (your Superbot credits, plan or limits), `superbot` (Superbot itself; retry), `model_server` (Superbot’s model service; retry shortly) or `provider` (a provider account you connected). More values may be added."}},"required":["type","message"]}},"required":["error"],"description":"OpenAI’s error envelope (chat, responses, models)."},"AnthropicError":{"type":"object","properties":{"type":{"type":"string","enum":["error"]},"error":{"type":"object","properties":{"type":{"type":"string"},"message":{"type":"string"},"origin":{"type":"string","enum":["vendor"],"description":"Present, `vendor`, only when this status is your own vendor credential’s answer (also the `x-superbot-error-origin` header)."},"vendor_status":{"type":"integer","description":"With `origin`: the vendor’s own HTTP status."},"source":{"type":"string","description":"Where the problem is: `request` (your request or conversation, e.g. too long for the model), `client` (your client or tool setup, e.g. its key), `account` (your Superbot credits, plan or limits), `superbot` (Superbot itself; retry), `model_server` (Superbot’s model service; retry shortly) or `provider` (a provider account you connected). More values may be added."}},"required":["type","message"]}},"required":["type","error"],"description":"Anthropic’s error envelope (messages)."},"TurnRecord":{"type":"object","properties":{"state":{"type":"string","enum":["running","done","error","cancelled","parked"],"description":"Where the turn stands."},"request_id":{"type":"string"},"text":{"type":"string","description":"The reply so far (`running`) or the whole reply (`done`)."},"assets":{"type":"array","items":{"$ref":"#/components/schemas/TurnAsset"},"description":"Only on a `done` turn, only when it made files, and only when the read is by a caller key that draws no cards (an automation step, a script): the files the reply names, one entry per file, in order. `text` is unchanged beside it."}},"required":["state","request_id"],"additionalProperties":{},"description":"One turn of a conversation: `running` carries the text so far, `done` the reply, `error` the reason and message."},"TurnAsset":{"type":"object","properties":{"name":{"type":"string","description":"A file name with its extension where one is known, ready to hand to a Gmail attachment or a Drive upload.","example":"Q3-report.pdf"},"mime":{"type":"string","description":"The file’s media type.","example":"application/pdf"},"size":{"type":"integer","minimum":0,"description":"The size in bytes."},"url":{"type":"string","description":"Where to fetch the bytes. A generated picture, sound or clip is at `/gen/`; an artifact is published at an unguessable, immutable public link (`/shared/` or `/gen/`) for a `zapier/` or `n8n/` caller, and answered by its signed artifact link (valid 24 hours) for any other."}},"required":["name","mime","size","url"],"description":"One file a turn made: a picture, a sound, a clip, a document."},"AgentPairPreview":{"type":"object","properties":{"kind":{"type":"string","enum":["agent_computer"]},"label":{"type":"string"},"agent_vendor":{"type":["string","null"]},"ip":{"type":["string","null"]},"geo":{"type":["string","null"]},"tier":{"type":"string","enum":["link"]},"approve_on":{"type":"string","enum":["this_device","phone"]},"asked_at":{"type":"string","description":"When the agent computer asked for this code (ISO-8601 UTC). Absent on an older edge."},"expires_at":{"type":"string","description":"When the code lapses (ISO-8601 UTC). Absent on an older edge."}},"required":["kind","label","agent_vendor","ip","geo","tier","approve_on"],"description":"What a pending bot-started agent computer code would link. A device code only ever grants the link tier."},"AgentPairApproveResponse":{"type":"object","properties":{"device_id":{"type":"string"},"kind":{"type":"string","enum":["agent_computer"]},"tier":{"type":"string","enum":["link"]}},"required":["device_id","kind","tier"]},"AgentPairDenyResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]},"TurnCallbackAccepted":{"type":"object","properties":{"session":{"type":"string","description":"The conversation the turn runs in: what `x-superbot-session` named, else the id the gateway derived."},"request_id":{"type":"string","description":"The turn’s id (also the response’s `x-request-id`): the `request` of `GET /v1/turns/{session}`."}},"required":["session","request_id"]},"ChatCompletionRequest":{"type":"object","properties":{"model":{"type":"string","example":"superbot"}},"required":["model"],"additionalProperties":{},"description":"An OpenAI Chat Completions request body."},"ResponseRequest":{"type":"object","properties":{"model":{"type":"string","example":"superbot"}},"required":["model"],"additionalProperties":{},"description":"An OpenAI Responses request body."},"MessageRequest":{"type":"object","properties":{"model":{"type":"string","example":"superbot"}},"required":["model"],"additionalProperties":{},"description":"An Anthropic Messages request body."},"TokenCount":{"type":"object","properties":{"input_tokens":{"type":"integer"}},"required":["input_tokens"]},"CountTokensRequest":{"type":"object","properties":{"model":{"type":"string","example":"superbot"}},"required":["model"],"additionalProperties":{},"description":"An Anthropic Messages body; only `messages` is read."},"ModelList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Model"}}},"required":["object","data"]},"UsageAggregate":{"type":"object","properties":{"object":{"type":"string","enum":["generation"]},"window":{"type":"string","enum":["day","week","month"]},"key":{"type":"string"},"key_label":{"type":"string"},"native_tokens_prompt":{"type":"number"},"native_tokens_completion":{"type":"number"},"cache_read":{"type":"number"},"cache_write":{"type":"number"},"total_cost":{"type":"number"},"cache_discount":{"type":"number"},"is_byok":{"type":"boolean"},"model":{"type":"string"},"models":{"type":"array","items":{"type":"string"}},"status":{"type":"integer"},"ttft_ms":{"type":"number"},"latency_ms":{"type":"number"},"count":{"type":"integer"},"data":{"type":"array","items":{"$ref":"#/components/schemas/UsageGeneration"}}},"required":["object","window","key","key_label","native_tokens_prompt","native_tokens_completion","cache_read","cache_write","total_cost","cache_discount","is_byok","models","count","data"]},"UsagePeriod":{"type":"object","properties":{"period":{"type":"string","enum":["week","month","all"]},"since":{"type":["string","null"]},"paid_usd":{"type":"number"},"list_usd":{"type":"number"},"saved_usd":{"type":"number"}},"required":["period","since","paid_usd","list_usd","saved_usd"]},"UsageGenerationList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/UsageGeneration"}}},"required":["object","data"]},"CallerKeyList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/CallerKey"}},"has_more":{"type":"boolean"},"first_id":{"type":["string","null"],"description":"Id of the first item on this page; pass as `before_id` for the previous page."},"last_id":{"type":["string","null"],"description":"Id of the last item on this page; pass as `after_id` for the next page."},"keys":{"type":"array","items":{"$ref":"#/components/schemas/CallerKey"},"description":"Legacy: the same rows as `data`."}},"required":["object","data","has_more","first_id","last_id","keys"]},"CreatedKey":{"type":"object","properties":{"key":{"type":"string","description":"The plaintext `sbc_…` key, shown once."},"row":{"$ref":"#/components/schemas/CallerKey"}},"required":["key","row"]},"CreateKeyRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":64,"description":"What the tool calls itself, 1-64 chars. Required unless `person` is given, then it defaults to the person's name."},"person":{"$ref":"#/components/schemas/KeyPerson"},"route":{"type":"string","enum":["byo","credits","auto"]},"mode":{"type":"string","enum":["model","agent"]},"daily_limit_tokens":{"type":"number","description":"Daily spend cap in whole credits."},"monthly_limit_tokens":{"type":"number","description":"Monthly spend cap in whole credits."},"allowed_models":{"type":"array","items":{"type":"string"},"description":"Glob allow-list over model names; with models_listed, the exact canonical ids (no globs)."},"models_listed":{"type":"boolean","description":"true = the listed reading: the key dials exactly its allowed_models, listed as the per-app picker names; empty = none. A PATCH that omits it leaves it as it was."},"model_pins":{"type":["object","null"],"additionalProperties":{"type":"string"},"description":"Canonical model id to the stable account id it is pinned to (non-empty strings). A PATCH replaces the whole map; null clears it."},"model_aliases":{"type":["object","null"],"additionalProperties":{"type":"string"},"description":"Canonical model id (a member of allowed_models) to the custom name its picker shows (1-64 characters: letters, numbers, dots, dashes, colons). A PATCH replaces the whole map; null clears it. A refused name stores nothing and answers the reason. Removing a model from allowed_models drops its custom name."},"default_model":{"type":["string","null"],"description":"The model a call that names the bare house agent `superbot` (the default model of Zapier and n8n), or names no model, is answered by instead: `superbot-fast`, `superbot-omni`, or a model of one of your own accounts (`claude-sonnet-5-5`, `gpt-5.5`, `custom/<endpoint>/<id>`). A call that names any other model is dialled as named. `null` or `superbot` clears it. A model of your own account needs a key on route `auto` or `byo` in mode `model` whose `allowed_models` admits it; a key on route `credits` takes a house model only, and a key with `models_listed` takes none. The write is judged on the key as it will be stored, so a PATCH that would leave the default unusable (route credits, mode agent, a narrower list) answers 400 `invalid_default_model`: send `default_model: null` with it. A PATCH that omits it leaves it as it was."},"incognito":{"type":"boolean"},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/Scope"},"description":"Explicit scopes; wins over `preset`."},"app":{"type":"string","description":"Forwarding app this listed key's model names are spelled for: cursor, copilot-cli, cline, roo, qwen-code, hermes, openclaw, zazen, default. Set at creation, cannot be changed. Absent = cursor."},"preset":{"type":"string","enum":["gateway","read_only","full"],"description":"A named scope set."}}},"KeyPerson":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":64,"description":"The person's display name, 1-64 printable characters (no `<`, `>`, `\"` or `'`). Required for a new person; with `id` it must equal the stored name or be left out."},"email":{"type":"string","maxLength":254,"description":"The person's email address. With `id` it must equal the stored one or be left out."},"group":{"type":"string","minLength":1,"maxLength":64,"description":"A free-text grouping, 1-64 characters. With `id` it must equal the stored one or be left out."},"id":{"type":"string","pattern":"^per_[0-9a-f]{16}$","description":"The `person_id` of a person already on this account: adds another key for them, which inherits the stored name, email, group, prompt_history and paused_at (a paused person's new key is born paused). Rotating a key is a mint with the same `id`, then a revoke of the old key.","example":"per_9f2c41d0a7b35e68"}},"description":"The person a key is minted for. Without `id` it makes a new person (`name` required); with `id` it adds a key to that person. A person key stamps no device (the minting device's logout never revokes it), takes no `org_id` and is billed to the owner."},"CurrentKey":{"type":"object","properties":{"row":{"$ref":"#/components/schemas/CallerKey"},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/Scope"}},"usage":{"$ref":"#/components/schemas/KeyUsage"}},"required":["row","scopes","usage"]},"KeyUsage":{"type":"object","properties":{"day":{"$ref":"#/components/schemas/KeyUsageWindow"},"week":{"$ref":"#/components/schemas/KeyUsageWindow"},"month":{"$ref":"#/components/schemas/KeyUsageWindow"}},"required":["day","week","month"],"description":"This key's own metered usage in three windows: `day` is the trailing 24 hours (the daily cap's window), `week` the trailing 7 days, `month` the current UTC calendar month (the monthly cap's window). Each window reports `requests` (every metered request), `prompts` (the requests that were the person's own text), `tokens` and `billed_usd`."},"KeyUsageWindow":{"type":"object","properties":{"requests":{"type":"integer","description":"Distinct metered requests (a request that dialed several times counts once). Every request the key made is one, an agent's tool legs, a title helper and a probe included: the call volume, not what the person asked."},"prompts":{"type":"integer","description":"Distinct answered prompts: requests whose last message was the person's own text and that were answered (the gateway marks the request's row only then), counted once per request id. A tool leg, a title helper, a probe and a refused or failed call are requests but not prompts. Only the dials the gateway wrote a row for are read, so the relay door's turns are not counted here."},"tokens":{"type":"number","description":"Every metered leg: fresh input, output and both cache legs."},"billed_usd":{"type":"number","description":"What the window's calls are worth to the caps and the usage pages, USD: the router's settle once read back, else the metered list value."},"clients":{"type":"object","properties":{"zapier":{"type":"integer"},"n8n":{"type":"integer"}},"description":"Distinct requests of the window made by Zapier or n8n, counted from the `x-superbot-client` tag (`zapier/<v>`, `n8n/<v>`) the request carried. A platform with no request in the window is absent, and the member is absent when neither made one."}},"required":["requests","prompts","tokens","billed_usd"]},"UpdatedKey":{"type":"object","properties":{"row":{"$ref":"#/components/schemas/CallerKey"}},"required":["row"]},"UpdateKeyRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":64},"route":{"type":"string","enum":["byo","credits","auto"]},"mode":{"type":"string","enum":["model","agent"]},"daily_limit_tokens":{"type":"number","description":"Daily spend cap in whole credits."},"monthly_limit_tokens":{"type":"number","description":"Monthly spend cap in whole credits."},"allowed_models":{"type":"array","items":{"type":"string"},"description":"Glob allow-list over model names; with models_listed, the exact canonical ids (no globs)."},"models_listed":{"type":"boolean","description":"true = the listed reading: the key dials exactly its allowed_models, listed as the per-app picker names; empty = none. A PATCH that omits it leaves it as it was."},"model_pins":{"type":["object","null"],"additionalProperties":{"type":"string"},"description":"Canonical model id to the stable account id it is pinned to (non-empty strings). A PATCH replaces the whole map; null clears it."},"model_aliases":{"type":["object","null"],"additionalProperties":{"type":"string"},"description":"Canonical model id (a member of allowed_models) to the custom name its picker shows (1-64 characters: letters, numbers, dots, dashes, colons). A PATCH replaces the whole map; null clears it. A refused name stores nothing and answers the reason. Removing a model from allowed_models drops its custom name."},"default_model":{"type":["string","null"],"description":"The model a call that names the bare house agent `superbot` (the default model of Zapier and n8n), or names no model, is answered by instead: `superbot-fast`, `superbot-omni`, or a model of one of your own accounts (`claude-sonnet-5-5`, `gpt-5.5`, `custom/<endpoint>/<id>`). A call that names any other model is dialled as named. `null` or `superbot` clears it. A model of your own account needs a key on route `auto` or `byo` in mode `model` whose `allowed_models` admits it; a key on route `credits` takes a house model only, and a key with `models_listed` takes none. The write is judged on the key as it will be stored, so a PATCH that would leave the default unusable (route credits, mode agent, a narrower list) answers 400 `invalid_default_model`: send `default_model: null` with it. A PATCH that omits it leaves it as it was."},"incognito":{"type":"boolean"},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/Scope"},"description":"Explicit scopes; wins over `preset`."},"person_name":{"type":"string","minLength":1,"maxLength":64,"description":"Rename the person (1-64 printable characters). Cannot be cleared. Does not rename the key (`name`)."},"person_email":{"type":["string","null"],"maxLength":254,"description":"Set the person's email address; null clears it."},"person_group":{"type":["string","null"],"minLength":1,"maxLength":64,"description":"Set the person's group; null clears it."},"prompt_history":{"allOf":[{"$ref":"#/components/schemas/PromptHistory"},{"type":["object","null"]}]},"paused_at":{"anyOf":[{"type":"boolean"},{"type":"string"},{"type":"null"}],"description":"`true` pauses the person now (the edge stamps the time), an ISO 8601 time pauses from then (not in the future), `false` or null resumes. A paused person's keys answer 403 `key_paused` at the model gateway, the `/v1/keys` routes, the relay door and the Cosmos door; every other route does not recognise a held key and answers 401 `unauthorized`."}}},"RevokedKey":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"already":{"type":"boolean"}},"required":["ok"]},"RotatedKey":{"type":"object","properties":{"key":{"type":"string","description":"The new key in plaintext. Shown once."},"row":{"$ref":"#/components/schemas/CallerKey"},"revoked":{"type":["string","null"],"description":"The id of the key that was revoked, or null if that revoke failed after the mint."}},"required":["key","row","revoked"]},"UpstreamList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Upstream"}},"has_more":{"type":"boolean"},"first_id":{"type":["string","null"],"description":"Id of the first item on this page; pass as `before_id` for the previous page."},"last_id":{"type":["string","null"],"description":"Id of the last item on this page; pass as `after_id` for the next page."},"upstreams":{"type":"array","items":{"$ref":"#/components/schemas/Upstream"},"description":"Legacy: the same rows as `data`."}},"required":["object","data","has_more","first_id","last_id","upstreams"]},"UpstreamWithProbe":{"type":"object","properties":{"upstream":{"$ref":"#/components/schemas/Upstream"},"probe":{"$ref":"#/components/schemas/UpstreamProbe"}},"required":["upstream","probe"]},"CreateUpstreamRequest":{"type":"object","properties":{"label":{"type":"string"},"base_url":{"type":"string"},"api_key":{"type":"string"},"dialect":{"type":"string","enum":["openai","anthropic","auto"]},"headers":{"type":"object","additionalProperties":{"type":"string"}},"models":{"type":"array","items":{"type":"string"}}},"required":["label","base_url","api_key"]},"UpdateUpstreamRequest":{"type":"object","properties":{"label":{"type":"string"},"dialect":{"type":"string","enum":["openai","anthropic"]},"api_key":{"type":"string"},"models":{"type":"array","items":{"type":"string"}},"model_names":{"type":"object","additionalProperties":{"type":"string"}}}},"AliasWrite":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"token":{"type":"string"},"rev":{"type":"integer"}},"required":["ok","token","rev"]},"SetAliasRequest":{"type":"object","properties":{"vendor":{"type":"string"},"model_id":{"type":"string"},"label":{"type":"string","maxLength":120},"custody":{"type":"string","enum":["envelope","device-held"]}},"required":["vendor"]},"TeamList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Team"}},"has_more":{"type":"boolean"},"first_id":{"type":["string","null"],"description":"Id of the first item on this page; pass as `before_id` for the previous page."},"last_id":{"type":["string","null"],"description":"Id of the last item on this page; pass as `after_id` for the next page."}},"required":["object","data","has_more","first_id","last_id"]},"CreateTeamRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120}},"required":["name"]},"UpdateTeamRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"share_defaults":{"type":"object","properties":{"mcp":{"type":"boolean"},"rules":{"type":"boolean"},"skills":{"type":"boolean"}},"required":["mcp","rules","skills"],"description":"What a new member pools by default, per kind."},"share_policy":{"type":"string","enum":["members","editors"],"description":"Who may add items to the pool."},"require_manual_confirm":{"type":"boolean","description":"Whether an admin must confirm each new member before they receive team secrets."}}},"DeletedTeam":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["team"]},"deleted":{"type":"boolean","enum":[true]}},"required":["id","object","deleted"]},"TeamMemberList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/TeamMember"}},"has_more":{"type":"boolean"},"first_id":{"type":["string","null"],"description":"Id of the first item on this page; pass as `before_id` for the previous page."},"last_id":{"type":["string","null"],"description":"Id of the last item on this page; pass as `after_id` for the next page."}},"required":["object","data","has_more","first_id","last_id"]},"UpdateTeamMemberRequest":{"type":"object","properties":{"role":{"$ref":"#/components/schemas/TeamRole"}},"required":["role"]},"RemovedTeamMember":{"type":"object","properties":{"object":{"type":"string","enum":["team_member"]},"user_id":{"type":"string"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","user_id","deleted"]},"TeamInviteList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/TeamInvite"}},"has_more":{"type":"boolean"},"first_id":{"type":["string","null"],"description":"Id of the first item on this page; pass as `before_id` for the previous page."},"last_id":{"type":["string","null"],"description":"Id of the last item on this page; pass as `after_id` for the next page."}},"required":["object","data","has_more","first_id","last_id"]},"CreateTeamInviteRequest":{"type":"object","properties":{"email":{"type":"string","minLength":3,"maxLength":254},"role":{"$ref":"#/components/schemas/TeamRole"}},"required":["email"]},"RevokedTeamInvite":{"type":"object","properties":{"object":{"type":"string","enum":["team_invite"]},"code":{"type":"string"},"revoked":{"type":"boolean","enum":[true]}},"required":["object","code","revoked"]},"AcceptTeamInviteRequest":{"type":"object","properties":{"share":{"type":"object","properties":{"mcp":{"type":"boolean"},"rules":{"type":"boolean"},"skills":{"type":"boolean"}},"description":"What to pool into the team, per kind."}}},"DeviceList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Device"}},"has_more":{"type":"boolean"},"first_id":{"type":["string","null"],"description":"Id of the first item on this page; pass as `before_id` for the previous page."},"last_id":{"type":["string","null"],"description":"Id of the last item on this page; pass as `after_id` for the next page."}},"required":["object","data","has_more","first_id","last_id"]},"DeletedDevice":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["device"]},"deleted":{"type":"boolean","enum":[true]},"agent_unlink":{"$ref":"#/components/schemas/AgentUnlink"}},"required":["id","object","deleted"],"description":"A device that was unlinked: its tokens and the caller keys it minted are revoked."},"AgentUnlink":{"type":"object","properties":{"device_id":{"type":"string"},"reason":{"type":"string","enum":["user","revoked","link_idle"]},"cancelled":{"type":"object","properties":{"jobs":{"type":"integer"},"terminals":{"type":"integer"},"loci":{"type":"integer"},"prompts":{"type":"integer"},"pair_requests":{"type":"integer"},"live_sessions":{"type":"integer"},"automations":{"type":"integer"}},"required":["jobs","terminals","loci","prompts","pair_requests","live_sessions","automations"]},"key":{"type":"object","properties":{"holder_removed":{"type":"boolean"},"factor_wraps_removed":{"type":"integer"},"rotation":{"type":"string","enum":["enqueued","no_holder_device","not_needed"]}},"required":["holder_removed","factor_wraps_removed","rotation"]},"rotate_at_source":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"adapter":{"type":"string"},"label":{"type":["string","null"]},"class":{"type":"string"}},"required":["kind","adapter","label","class"],"description":"A credential the agent computer could decrypt: rotate it at its provider. A reference, never a value."}}},"required":["device_id","reason","cancelled","key","rotate_at_source"],"description":"What unlinking an agent computer did, and the credentials to rotate at the source."},"UsageReport":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/UsageBucket"}},"has_more":{"type":"boolean"},"next_page":{"type":["string","null"],"description":"Pass as `page` for the next buckets; null on the last page."}},"required":["object","data","has_more","next_page"],"description":"Usage in fixed-width UTC buckets, oldest first; empty buckets carry `results: []`."},"CreatedRun":{"allOf":[{"$ref":"#/components/schemas/Run"},{"type":"object","properties":{"webhook_secret":{"type":"string","description":"The signing secret for `webhook_url`, returned ONCE, here. Verify each delivery: `X-Superbot-Signature: t=<unix>,v1=<hex>` where v1 is HMAC-SHA256(secret, `t + \".\" + body`)."}}}],"description":"The run just started, plus its webhook secret when one was asked for."},"RunBudget":{"type":["object","null"],"properties":{"max_wall_ms":{"type":"integer"},"max_usd":{"type":"number"},"max_legs":{"type":"integer"},"leg_ms":{"type":"integer"}},"required":["max_wall_ms","max_usd","max_legs","leg_ms"],"description":"What the run may spend: wall time, USD and legs."},"Run":{"type":"object","properties":{"id":{"type":"string","example":"run_3k9x0q2m1v"},"object":{"type":"string","enum":["run"]},"status":{"type":"string","enum":["queued","running","done","failed","needs_merge","cancelled"],"description":"`queued`, `running`, then one of `done`, `failed`, `needs_merge` (the work is on `branch` and waits for a merge) or `cancelled`."},"source":{"type":"string","enum":["app","api","cli","routine","slack","linear","jira","github"],"description":"What started the run. Runs started here are `api`."},"project":{"type":"string","description":"The project the run works on."},"prompt":{"type":["string","null"],"description":"The prompt, which is also the run’s title: show this to name the run. Null under zero data retention."},"mode":{"type":"string","enum":["agent","plan","debug"]},"landing":{"type":"string","enum":["main","pr"],"description":"`main` lands the work on the default branch; `pr` opens a pull request."},"budget":{"$ref":"#/components/schemas/RunBudget"},"usd_spent":{"type":["number","null"]},"served_model":{"type":["string","null"],"description":"The model that served the run, as the runner reported it when the run settled (the same `served_model` the swarm reports). Null until then, and on a run that settled before this field existed."},"served_lane":{"type":["string","null"],"enum":["platform",null],"description":"Who served the run’s model calls (the same `served_lane` the swarm reports). Every cloud run is `platform`: Superbot’s own model key, charged in credits to the account. Null on a run that predates this field."},"branch":{"type":["string","null"],"description":"The branch the work sits on, when it did not land directly."},"landed_commit":{"type":["string","null"]},"summary":{"type":["string","null"],"description":"The runner’s end-of-run diagnostic once it settles, a machine-readable line for debugging and for telling a failed run from a finished one (for example `done — sandbox fence-only, 127 tool call(s), local space sp_…`), and it can name internal ids. It is not a title and not the run’s answer: name the run by `prompt`, and do not show this text to end users. Null under zero data retention."},"pr_url":{"type":["string","null"]},"url":{"type":["string","null"],"description":"A deep link that opens the run’s project in the Superbot app (`superbot://project/<id>`), when the project id is linkable."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","object","status","source","project","prompt","mode","landing","budget","usd_spent","branch","landed_commit","summary","pr_url","url","created_at","updated_at"],"description":"One cloud agent run on a project."},"RunList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Run"}},"has_more":{"type":"boolean"},"first_id":{"type":["string","null"],"description":"Id of the first item on this page; pass as `before_id` for the previous page."},"last_id":{"type":["string","null"],"description":"Id of the last item on this page; pass as `after_id` for the next page."}},"required":["object","data","has_more","first_id","last_id"]},"RunProjectList":{"type":"object","properties":{"projects":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The project id to pass as `project` to createRun.","example":"prj_7f3a"},"name":{"type":"string","description":"The project’s name in the Superbot app."}},"required":["id","name"]}}},"required":["projects"],"description":"Your projects linked to one repository: id and name only."},"RunEventList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/RunEvent"}},"next_after":{"type":"integer","description":"Pass as `after` on the next poll."},"done":{"type":"boolean","description":"True once nothing more will happen to the run."}},"required":["object","data","next_after","done"]},"RunEvent":{"type":"object","properties":{"object":{"type":"string","enum":["run.event"]},"run_id":{"type":"string"},"seq":{"type":"integer","description":"Per-run sequence number; the SSE `id`, and what `after` / `Last-Event-ID` resume from."},"type":{"type":"string","enum":["status","result","pr","note_queued","note_delivered"]},"created_at":{"type":"string"},"note_id":{"type":"string","description":"On `note_queued` / `note_delivered`: the note’s id (never its text)."},"length":{"type":"integer","description":"On `note_queued` / `note_delivered`: the note’s length in characters."},"status":{"type":"string","enum":["queued","running","done","failed","needs_merge","cancelled"]},"branch":{"type":"string"},"landed_commit":{"type":"string"},"usd_spent":{"type":"number"},"served_model":{"type":"string","description":"On `result` only: the model that served the run, as `served_model` on the run."},"served_lane":{"type":"string","enum":["platform"],"description":"On `result` only: who served the run, as `served_lane` on the run."},"summary":{"type":["string","null"],"description":"On `result` only: the runner’s end-of-run diagnostic, as `summary` on the run (not a title or an answer). Null under zero data retention."},"pr_url":{"type":"string"},"pr_number":{"type":"integer"},"pr_state":{"type":"string"},"publish_error":{"type":"string"}},"required":["object","run_id","seq","type","created_at"],"description":"A status change, the settled result, the pull request a `pr` run opened, or a steering note queued on the run and then delivered to it."},"RunNote":{"type":"object","properties":{"id":{"type":"string","example":"note_4f1c9a0b2e7d6c3a18"},"object":{"type":"string","enum":["run.note"]},"run_id":{"type":"string"},"queued_at":{"type":"string"}},"required":["id","object","run_id","queued_at"],"description":"A note queued for a running run."}},"parameters":{}},"paths":{"/v1/turns/{session}":{"get":{"operationId":"getTurn","summary":"Read a turn","description":"Where a turn of one of your conversations stands: `running` with the text so far, `done` with the reply (and `assets`, the files it made, for a caller key that draws no cards), `error`, `cancelled`. `?request=` names one turn (the `request_id` of an async call’s 202, from either form: `x-superbot-callback-url` or `Prefer: respond-async`); without it the conversation’s newest turn. A turn the gateway admitted reads `running` (empty `text`) from the moment of its 202, before the agent has produced a frame, so a poll that starts at once never sees a gap; one an earlier process lost after admitting it reads `error` with reason `interrupted`. Turns are stored for 24 hours. Needs the `turns:read` scope; the read bills nothing. A missing or unknown bearer is `401`, a key without the scope `403 insufficient_scope`, a request id this account never admitted `404 no_turn` and a deleted conversation `410 chat_deleted`.","tags":["Gateway"],"security":[{"callerKey":["turns:read"]},{"apiKeyHeader":["turns:read"]},{"session":[]}],"x-superbot-scopes":["turns:read"],"parameters":[{"schema":{"type":"string","description":"The conversation id (what `x-superbot-session` named, or the `session` of an async call’s 202)."},"required":true,"description":"The conversation id (what `x-superbot-session` named, or the `session` of an async call’s 202).","name":"session","in":"path"},{"schema":{"type":"string","description":"A turn’s request id."},"required":false,"description":"A turn’s request id.","name":"request","in":"query"}],"responses":{"200":{"description":"The turn.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TurnRecord"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/turns/{session}/stream":{"get":{"operationId":"streamTurn","summary":"Re-attach to a turn’s stream","description":"Server-sent events: every journaled frame of the turn after `after` (or `Last-Event-ID`), then the live frames until its `answer` or `error`. A cursor past the journal gets one `resync` with the text so far. Needs the `turns:read` scope.","tags":["Gateway"],"security":[{"callerKey":["turns:read"]},{"apiKeyHeader":["turns:read"]},{"session":[]}],"x-superbot-scopes":["turns:read"],"parameters":[{"schema":{"type":"string","description":"The conversation id (what `x-superbot-session` named, or the `session` of an async call’s 202)."},"required":true,"description":"The conversation id (what `x-superbot-session` named, or the `session` of an async call’s 202).","name":"session","in":"path"},{"schema":{"type":"string","description":"The turn’s request id (required)."},"required":true,"description":"The turn’s request id (required).","name":"request","in":"query"},{"schema":{"type":"string","description":"The last frame id already seen."},"required":false,"description":"The last frame id already seen.","name":"after","in":"query"}],"responses":{"200":{"description":"The turn’s frames as server-sent events.","content":{"text/event-stream":{"schema":{"type":"string"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/devices/{device_id}/jobs":{"post":{"operationId":"createAgentJob","summary":"Run a job on an agent computer","description":"Queue one device-shell job on a linked agent computer, by its id. First-party only: a session or a device token of your own Superbot app; agent computer tokens, MCP connectors, caller keys and the account API key are refused (403). An asleep agent computer answers `queued_asleep`; the job waits for its next poll up to 600 s.","tags":["Devices"],"security":[{"callerKey":["devices:write"]},{"apiKeyHeader":["devices:write"]},{"session":[]}],"x-superbot-scopes":["devices:write"],"parameters":[{"schema":{"type":"string","description":"An agent computer (`agt_…`) on your account."},"required":true,"description":"An agent computer (`agt_…`) on your account.","name":"device_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentJobEnqueueBody"}}}},"responses":{"201":{"description":"Queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentJobEnqueueResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/devices/{device_id}/jobs/{job_id}":{"get":{"operationId":"getAgentJob","summary":"Read an agent computer job","description":"The job and, once it is `done` or `failed`, its result. `wait` (seconds, at most 25) parks the read until the job settles. A job lost to a Superbot restart answers 410 `job_lost_in_restart` (`retryable: true`, `kind`): it may have run on the agent computer, so check before repeating anything that changes state, then send it again. An id nobody minted, another account's, or older than the 600 s job lifetime is 404 `job_not_found`.","tags":["Devices"],"security":[{"callerKey":["devices:read"]},{"apiKeyHeader":["devices:read"]},{"session":[]}],"x-superbot-scopes":["devices:read"],"parameters":[{"schema":{"type":"string","description":"An agent computer (`agt_…`) on your account."},"required":true,"description":"An agent computer (`agt_…`) on your account.","name":"device_id","in":"path"},{"schema":{"type":"string","description":"The job id the enqueue answered."},"required":true,"description":"The job id the enqueue answered.","name":"job_id","in":"path"},{"schema":{"type":"string","description":"Seconds to wait for the job to settle, 0-25."},"required":false,"description":"Seconds to wait for the job to settle, 0-25.","name":"wait","in":"query"}],"responses":{"200":{"description":"The job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentJobView"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"410":{"description":"Superbot restarted after the job was queued and its outcome was not kept (`job_lost_in_restart`, `retryable: true`, `kind`). Send the job again once a repeat is safe.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/devices/{device_id}/terminals/{terminal_id}/stream":{"get":{"operationId":"streamAgentTerminal","summary":"Stream an agent computer terminal","description":"Server-sent events, every frame `event: terminal` with an AgentTerminalFrame as JSON: `output` (seq strictly increasing), then `exit` or `gone`, after which the stream closes. Resume with `since=<seq>` (or Last-Event-ID). Open a terminal with a `bash` job `{command: <login shell>, runInBackground: true, interactive: true}` (a real tty: prompts, sudo and TUIs work) and type into it with `bash_write`.","tags":["Devices"],"security":[{"callerKey":["devices:read"]},{"apiKeyHeader":["devices:read"]},{"session":[]}],"x-superbot-scopes":["devices:read"],"parameters":[{"schema":{"type":"string","description":"An agent computer (`agt_…`) on your account."},"required":true,"description":"An agent computer (`agt_…`) on your account.","name":"device_id","in":"path"},{"schema":{"type":"string","description":"The terminal id a background `bash` job answered."},"required":true,"description":"The terminal id a background `bash` job answered.","name":"terminal_id","in":"path"},{"schema":{"type":"string","description":"Resume after this output seq (a byte cursor). Absent: from the start of the buffer."},"required":false,"description":"Resume after this output seq (a byte cursor). Absent: from the start of the buffer.","name":"since","in":"query"}],"responses":{"200":{"description":"The terminal stream.","content":{"text/event-stream":{"schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/pair/{user_code}":{"get":{"operationId":"previewAgentPair","summary":"Preview an agent computer code","description":"The details of a pending code an agent computer showed. First-party only: your own Superbot app (a session or its device token).","tags":["Devices"],"security":[{"callerKey":[]},{"apiKeyHeader":[]},{"session":[]}],"x-superbot-scopes":[],"parameters":[{"schema":{"type":"string","description":"The code the agent computer shows (e.g. `ABCD-EFGH`)."},"required":true,"description":"The code the agent computer shows (e.g. `ABCD-EFGH`).","name":"user_code","in":"path"}],"responses":{"200":{"description":"The pending code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentPairPreview"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/pair/{user_code}/approve":{"post":{"operationId":"approveAgentPair","summary":"Approve an agent computer code","description":"Link the agent computer behind a pending code at the link tier (terminal and relay, no synced data). First-party only; a web session with a recent phone is told to finish on the phone (409 approve_on_phone).","tags":["Devices"],"security":[{"callerKey":[]},{"apiKeyHeader":[]},{"session":[]}],"x-superbot-scopes":[],"parameters":[{"schema":{"type":"string","description":"The code the agent computer shows (e.g. `ABCD-EFGH`)."},"required":true,"description":"The code the agent computer shows (e.g. `ABCD-EFGH`).","name":"user_code","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","description":"A new label, 1-32 characters."}}}}}},"responses":{"200":{"description":"Linked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentPairApproveResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/pair/{user_code}/deny":{"post":{"operationId":"denyAgentPair","summary":"Decline an agent computer code","description":"Decline a pending code (\"Not me\"). The agent computer's next poll of its device code answers `access_denied` (RFC 8628 §3.5) and the code is dead. `reason` `not_me` says the user never asked for it: it is logged with the claimed vendor and the request network, and three distinct accounts reporting one network inside 24 hours count against that network's code limit. First-party only. 404 `not_found` for a code that is unknown, expired, approved or already declined.","tags":["Devices"],"security":[{"callerKey":[]},{"apiKeyHeader":[]},{"session":[]}],"x-superbot-scopes":[],"parameters":[{"schema":{"type":"string","description":"The code the agent computer shows (e.g. `ABCD-EFGH`)."},"required":true,"description":"The code the agent computer shows (e.g. `ABCD-EFGH`).","name":"user_code","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","enum":["cancel","not_me"],"description":"Why. Default `cancel`."}}}}}},"responses":{"200":{"description":"Declined.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentPairDenyResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/chat/completions":{"post":{"operationId":"createChatCompletion","summary":"Create a chat completion","description":"OpenAI Chat Completions: passed through to your own vendor key, transcoded, or answered by your agent (`model: \"superbot\"`). A request that declares its own tools, the way Codex, Claude Code and Cursor do, is answered by the superbot model driving those tools: its tool calls come back in your dialect for your client to run. So is a call that caps its reply at 512 tokens or fewer, and a call that asks for structured output (a JSON object or a JSON schema), whose reply is the model’s output alone. Any other request is answered by your agent, and outside superbot’s own apps a card it draws comes back as plain markdown: a choice as a list, sources as a Sources: list. When the agent answers with files (a generated picture, sound or clip, a document), the reply carries them beside the text as a top-level `superbot_assets` array of `{name, mime, size, url}` (a streamed reply sends it on its last chunk before `[DONE]`), only for a caller that draws no cards and only when there are files; the text is unchanged. The `url` is a durable public link for a `zapier/` or `n8n/` client (`x-superbot-client`) and the artifact’s signed link (valid 24 hours) for any other caller. When your agent answers, its server-side memory is kept per conversation: name one with the `x-superbot-session` header, or superbot reads the id your client sends (`prompt_cache_key`, `metadata.session_id`, `metadata.conversation_id`, a Responses `conversation` or an Anthropic `metadata.user_id`), else it keys the conversation on its first message.","tags":["Gateway"],"security":[{"callerKey":["gateway:invoke"]},{"apiKeyHeader":["gateway:invoke"]}],"x-superbot-scopes":["gateway:invoke"],"externalDocs":{"url":"https://platform.openai.com/docs/api-reference/chat/create","description":"OpenAI Chat Completions reference"},"parameters":[{"schema":{"type":"string","enum":["byo","credits","auto"],"description":"Override the key’s route for this request."},"required":false,"description":"Override the key’s route for this request.","name":"x-superbot-route","in":"header"},{"schema":{"type":"string","enum":["model","agent"],"description":"Override the key’s mode for this request."},"required":false,"description":"Override the key’s mode for this request.","name":"x-superbot-mode","in":"header"},{"schema":{"type":"string","enum":["omni"],"description":"Run the agent lane on your computer (omni)."},"required":false,"description":"Run the agent lane on your computer (omni).","name":"x-superbot-engine","in":"header"},{"schema":{"type":"string","description":"Names the server-side conversation your agent continues: letters, digits, `_` and `-`, at most 59 characters."},"required":false,"description":"Names the server-side conversation your agent continues: letters, digits, `_` and `-`, at most 59 characters.","name":"x-superbot-session","in":"header"},{"schema":{"type":"string","description":"An https URL (a Zapier catch hook, an n8n webhook node). The call is accepted at once with `202 {session, request_id}`, the turn runs, and when it settles Superbot POSTs `{session, request_id, status, text}` to this URL (`status` is `done` or `error`; an error also carries `error: {code, message}`; a turn that made files also carries `assets`, the same list as the reply’s `superbot_assets`). The URL is a secret: it is stored sealed, never logged, and forgotten once delivered. A 2xx from your URL ends the delivery; a network error, 408, 429 or 5xx is retried (1 s, 5 s, 30 s, 2 min, 10 min). Each delivery carries `x-superbot-event: turn.settled` and a stable `x-superbot-delivery` id. Every refusal a plain call gets (401, 402, 403, 429, a bad body) is still answered synchronously and starts no turn. The reply is the non-streamed one whatever `stream` says. Name the thread with `x-superbot-session` to continue it; a key holding `turns:read` reads the same turn back at `GET /v1/turns/{session}?request={request_id}`."},"required":false,"description":"An https URL (a Zapier catch hook, an n8n webhook node). The call is accepted at once with `202 {session, request_id}`, the turn runs, and when it settles Superbot POSTs `{session, request_id, status, text}` to this URL (`status` is `done` or `error`; an error also carries `error: {code, message}`; a turn that made files also carries `assets`, the same list as the reply’s `superbot_assets`). The URL is a secret: it is stored sealed, never logged, and forgotten once delivered. A 2xx from your URL ends the delivery; a network error, 408, 429 or 5xx is retried (1 s, 5 s, 30 s, 2 min, 10 min). Each delivery carries `x-superbot-event: turn.settled` and a stable `x-superbot-delivery` id. Every refusal a plain call gets (401, 402, 403, 429, a bad body) is still answered synchronously and starts no turn. The reply is the non-streamed one whatever `stream` says. Name the thread with `x-superbot-session` to continue it; a key holding `turns:read` reads the same turn back at `GET /v1/turns/{session}?request={request_id}`.","name":"x-superbot-callback-url","in":"header"},{"schema":{"type":"string","description":"`respond-async` (RFC 7240) starts the turn and answers `202 {session, request_id}` with `Preference-Applied: respond-async` as soon as it is accepted; nothing is delivered, so read the result by polling `GET /v1/turns/{session}?request={request_id}` (or re-attach at `/stream`) with `turns:read`. The turn runs on whether or not you stay connected. It applies to the agent (the default for `model: superbot`); on a call that dials a model directly the preference is ignored, the call is answered as usual and the response carries no `Preference-Applied`. With `x-superbot-callback-url` too, the callback form is used. Every refusal a plain call gets is still answered synchronously and starts no turn. The reply is the non-streamed one whatever `stream` says.","example":"respond-async"},"required":false,"description":"`respond-async` (RFC 7240) starts the turn and answers `202 {session, request_id}` with `Preference-Applied: respond-async` as soon as it is accepted; nothing is delivered, so read the result by polling `GET /v1/turns/{session}?request={request_id}` (or re-attach at `/stream`) with `turns:read`. The turn runs on whether or not you stay connected. It applies to the agent (the default for `model: superbot`); on a call that dials a model directly the preference is ignored, the call is answered as usual and the response carries no `Preference-Applied`. With `x-superbot-callback-url` too, the callback form is used. Every refusal a plain call gets is still answered synchronously and starts no turn. The reply is the non-streamed one whatever `stream` says.","name":"Prefer","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"}}}},"responses":{"200":{"description":"The answer in the dialect you dialed; streamed as server-sent events when the body asks for `stream: true`.","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{},"description":"The dialect’s response object."}},"text/event-stream":{"schema":{"type":"string"}}}},"202":{"description":"Only with `x-superbot-callback-url` or `Prefer: respond-async`: the call was accepted and the turn is running. With the callback header the result is POSTed to that URL when it settles; with `Prefer: respond-async` alone nothing is delivered and the caller polls. `session` and `request_id` read it back with `turns:read`. `Preference-Applied: respond-async` names the preference whenever the call asked for it.","headers":{"Preference-Applied":{"description":"Present when the call sent `Prefer: respond-async`: `respond-async`.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TurnCallbackAccepted"}}}},"400":{"description":"The body is not JSON or the dialect refused it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"401":{"description":"Missing, malformed or unknown key. A 401 that carries `x-superbot-error-origin: vendor` is your vendor credential’s refusal, not the gateway’s.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"402":{"description":"The key’s budget or your credits are spent (`byo_url` on the body).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"403":{"description":"Revoked · insufficient_scope · model_not_allowed · no_vendor_credential · no_custom_upstream. A 403 that carries `x-superbot-error-origin: vendor` is your vendor credential’s refusal, not the gateway’s.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"429":{"description":"Over the per-key request bucket. A 429 that carries `x-superbot-error-origin: vendor` is your vendor’s rate limit, not the gateway’s.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"499":{"description":"The caller hung up; the agent turn keeps running."},"5XX":{"description":"The upstream’s own status, rendered in your dialect. When a status is your own vendor credential’s answer (a BYO or custom-endpoint dial) the response carries `x-superbot-error-origin: vendor` and `error.origin: \"vendor\"` with `error.vendor_status`; a refusal without them is the gateway’s own.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/responses":{"post":{"operationId":"createResponse","summary":"Create a response","description":"OpenAI Responses: `model: \"superbot\"` (or `superbot-omni`) runs your agent; a linked Codex login passes through. A request that declares its own tools, the way Codex, Claude Code and Cursor do, is answered by the superbot model driving those tools: its tool calls come back in your dialect for your client to run. So is a call that caps its reply at 512 tokens or fewer, and a call that asks for structured output (a JSON object or a JSON schema), whose reply is the model’s output alone. Any other request is answered by your agent, and outside superbot’s own apps a card it draws comes back as plain markdown: a choice as a list, sources as a Sources: list. When your agent answers, its server-side memory is kept per conversation: name one with the `x-superbot-session` header, or superbot reads the id your client sends (`prompt_cache_key`, `metadata.session_id`, `metadata.conversation_id`, a Responses `conversation` or an Anthropic `metadata.user_id`), else it keys the conversation on its first message.","tags":["Gateway"],"security":[{"callerKey":["gateway:invoke"]},{"apiKeyHeader":["gateway:invoke"]}],"x-superbot-scopes":["gateway:invoke"],"externalDocs":{"url":"https://platform.openai.com/docs/api-reference/responses/create","description":"OpenAI Responses reference"},"parameters":[{"schema":{"type":"string","enum":["byo","credits","auto"],"description":"Override the key’s route for this request."},"required":false,"description":"Override the key’s route for this request.","name":"x-superbot-route","in":"header"},{"schema":{"type":"string","enum":["model","agent"],"description":"Override the key’s mode for this request."},"required":false,"description":"Override the key’s mode for this request.","name":"x-superbot-mode","in":"header"},{"schema":{"type":"string","enum":["omni"],"description":"Run the agent lane on your computer (omni)."},"required":false,"description":"Run the agent lane on your computer (omni).","name":"x-superbot-engine","in":"header"},{"schema":{"type":"string","description":"Names the server-side conversation your agent continues: letters, digits, `_` and `-`, at most 59 characters."},"required":false,"description":"Names the server-side conversation your agent continues: letters, digits, `_` and `-`, at most 59 characters.","name":"x-superbot-session","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseRequest"}}}},"responses":{"200":{"description":"The answer in the dialect you dialed; streamed as server-sent events when the body asks for `stream: true`.","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{},"description":"The dialect’s response object."}},"text/event-stream":{"schema":{"type":"string"}}}},"400":{"description":"The body is not JSON or the dialect refused it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"401":{"description":"Missing, malformed or unknown key. A 401 that carries `x-superbot-error-origin: vendor` is your vendor credential’s refusal, not the gateway’s.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"402":{"description":"The key’s budget or your credits are spent (`byo_url` on the body).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"403":{"description":"Revoked · insufficient_scope · model_not_allowed · no_vendor_credential · no_custom_upstream. A 403 that carries `x-superbot-error-origin: vendor` is your vendor credential’s refusal, not the gateway’s.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"429":{"description":"Over the per-key request bucket. A 429 that carries `x-superbot-error-origin: vendor` is your vendor’s rate limit, not the gateway’s.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"499":{"description":"The caller hung up; the agent turn keeps running."},"5XX":{"description":"The upstream’s own status, rendered in your dialect. When a status is your own vendor credential’s answer (a BYO or custom-endpoint dial) the response carries `x-superbot-error-origin: vendor` and `error.origin: \"vendor\"` with `error.vendor_status`; a refusal without them is the gateway’s own.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/messages":{"post":{"operationId":"createMessage","summary":"Create a message","description":"Anthropic Messages, transcoded to the upstream the key routes to, or answered by your agent (`model: \"superbot\"`). A request that declares its own tools, the way Codex, Claude Code and Cursor do, is answered by the superbot model driving those tools: its tool calls come back in your dialect for your client to run. So is a call that caps its reply at 512 tokens or fewer, and a call that asks for structured output (a JSON object or a JSON schema), whose reply is the model’s output alone. Any other request is answered by your agent, and outside superbot’s own apps a card it draws comes back as plain markdown: a choice as a list, sources as a Sources: list. When your agent answers, its server-side memory is kept per conversation: name one with the `x-superbot-session` header, or superbot reads the id your client sends (`prompt_cache_key`, `metadata.session_id`, `metadata.conversation_id`, a Responses `conversation` or an Anthropic `metadata.user_id`), else it keys the conversation on its first message.","tags":["Gateway"],"security":[{"callerKey":["gateway:invoke"]},{"apiKeyHeader":["gateway:invoke"]}],"x-superbot-scopes":["gateway:invoke"],"externalDocs":{"url":"https://docs.anthropic.com/en/api/messages","description":"Anthropic Messages reference"},"parameters":[{"schema":{"type":"string","enum":["byo","credits","auto"],"description":"Override the key’s route for this request."},"required":false,"description":"Override the key’s route for this request.","name":"x-superbot-route","in":"header"},{"schema":{"type":"string","enum":["model","agent"],"description":"Override the key’s mode for this request."},"required":false,"description":"Override the key’s mode for this request.","name":"x-superbot-mode","in":"header"},{"schema":{"type":"string","enum":["omni"],"description":"Run the agent lane on your computer (omni)."},"required":false,"description":"Run the agent lane on your computer (omni).","name":"x-superbot-engine","in":"header"},{"schema":{"type":"string","description":"Names the server-side conversation your agent continues: letters, digits, `_` and `-`, at most 59 characters."},"required":false,"description":"Names the server-side conversation your agent continues: letters, digits, `_` and `-`, at most 59 characters.","name":"x-superbot-session","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageRequest"}}}},"responses":{"200":{"description":"The answer in the dialect you dialed; streamed as server-sent events when the body asks for `stream: true`.","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{},"description":"The dialect’s response object."}},"text/event-stream":{"schema":{"type":"string"}}}},"400":{"description":"The body is not JSON or the dialect refused it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"401":{"description":"Missing, malformed or unknown key. A 401 that carries `x-superbot-error-origin: vendor` is your vendor credential’s refusal, not the gateway’s.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"402":{"description":"The key’s budget or your credits are spent (`byo_url` on the body).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"403":{"description":"Revoked · insufficient_scope · model_not_allowed · no_vendor_credential · no_custom_upstream. A 403 that carries `x-superbot-error-origin: vendor` is your vendor credential’s refusal, not the gateway’s.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"429":{"description":"Over the per-key request bucket. A 429 that carries `x-superbot-error-origin: vendor` is your vendor’s rate limit, not the gateway’s.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"499":{"description":"The caller hung up; the agent turn keeps running."},"5XX":{"description":"The upstream’s own status, rendered in your dialect. When a status is your own vendor credential’s answer (a BYO or custom-endpoint dial) the response carries `x-superbot-error-origin: vendor` and `error.origin: \"vendor\"` with `error.vendor_status`; a refusal without them is the gateway’s own.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/messages/count_tokens":{"post":{"operationId":"countMessageTokens","summary":"Estimate input tokens","description":"A local estimate (characters / 4). No upstream call and no charge.","tags":["Gateway"],"security":[{"callerKey":[]},{"apiKeyHeader":[]}],"x-superbot-scopes":[],"externalDocs":{"url":"https://docs.anthropic.com/en/api/messages-count-tokens","description":"Anthropic count tokens reference"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountTokensRequest"}}}},"responses":{"200":{"description":"The estimate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenCount"}}}},"400":{"description":"The body is not JSON.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"401":{"description":"Missing, malformed or unknown key. A 401 that carries `x-superbot-error-origin: vendor` is your vendor credential’s refusal, not the gateway’s.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"403":{"description":"The key is revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/models":{"get":{"operationId":"listModels","summary":"List models","description":"The agent models first (`superbot`, `superbot-omni`, `superbot-fast`), then your linked vendors’ models, your custom endpoints’ ids as `custom/<slug>/<id>`, then the credits catalog.","tags":["Gateway"],"security":[{"callerKey":[]},{"apiKeyHeader":[]}],"x-superbot-scopes":[],"responses":{"200":{"description":"Every model this key can name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelList"}}}},"401":{"description":"Missing, malformed or unknown key. A 401 that carries `x-superbot-error-origin: vendor` is your vendor credential’s refusal, not the gateway’s.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}},"403":{"description":"The key is revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/usage":{"get":{"operationId":"getUsage","summary":"Get usage over a window","description":"With a caller key (or `key=<id>` from a session): that key’s burn over `window`, OpenRouter generation shape. From a session without `key`: paid-versus-list spend over `period`.","tags":["Usage & spend"],"security":[{"callerKey":["usage:read"]},{"apiKeyHeader":["usage:read"]},{"session":[]}],"x-superbot-scopes":["usage:read"],"parameters":[{"schema":{"type":"string","enum":["day","week","month"],"description":"Key usage window; default day."},"required":false,"description":"Key usage window; default day.","name":"window","in":"query"},{"schema":{"type":"string","description":"Key id to read (sessions only; a caller key reads itself)."},"required":false,"description":"Key id to read (sessions only; a caller key reads itself).","name":"key","in":"query"},{"schema":{"type":"string","enum":["week","month","all"],"description":"Account spend period (session without `key`); default week."},"required":false,"description":"Account spend period (session without `key`); default week.","name":"period","in":"query"}],"responses":{"200":{"description":"The key aggregate, or the account period projection.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/UsageAggregate"},{"$ref":"#/components/schemas/UsagePeriod"}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/v1/usage/requests":{"get":{"operationId":"listUsageRequests","summary":"List usage per request","description":"One generation per request, newest first.","tags":["Usage & spend"],"security":[{"callerKey":["usage:read"]},{"apiKeyHeader":["usage:read"]},{"session":[]}],"x-superbot-scopes":["usage:read"],"parameters":[{"schema":{"type":"string","description":"Key id to read (sessions only)."},"required":false,"description":"Key id to read (sessions only).","name":"key","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"Rows to return, 1-100; default 20."},"required":false,"description":"Rows to return, 1-100; default 20.","name":"limit","in":"query"}],"responses":{"200":{"description":"The generations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageGenerationList"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/v1/usage/daily":{"get":{"operationId":"getUsageDaily","summary":"Get usage per UTC day","description":"The account’s usage per UTC day across every key, with totals. A person key (one minted for a person) reads its own person’s usage here, never the account’s.","tags":["Usage & spend"],"security":[{"callerKey":["usage:read"]},{"apiKeyHeader":["usage:read"]},{"session":[]}],"x-superbot-scopes":["usage:read"],"parameters":[{"schema":{"type":"string","format":"date","description":"YYYY-MM-DD; default 30 days before `to`."},"required":false,"description":"YYYY-MM-DD; default 30 days before `to`.","name":"from","in":"query"},{"schema":{"type":"string","format":"date","description":"YYYY-MM-DD; default today (UTC)."},"required":false,"description":"YYYY-MM-DD; default today (UTC).","name":"to","in":"query"}],"responses":{"200":{"description":"One row per day.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageDaily"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/v1/usage/breakdown":{"get":{"operationId":"getUsageBreakdown","summary":"Get usage bucketed and grouped","description":"Usage bucketed by hour or day, grouped by key, lane, role, session or model, narrowed by any filter. A person key reads its own person’s usage here, never the account’s.","tags":["Usage & spend"],"security":[{"callerKey":["usage:read"]},{"apiKeyHeader":["usage:read"]},{"session":[]}],"x-superbot-scopes":["usage:read"],"parameters":[{"schema":{"type":"string","format":"date","description":"YYYY-MM-DD; default 30 days before `to`."},"required":false,"description":"YYYY-MM-DD; default 30 days before `to`.","name":"from","in":"query"},{"schema":{"type":"string","format":"date","description":"YYYY-MM-DD; default today (UTC)."},"required":false,"description":"YYYY-MM-DD; default today (UTC).","name":"to","in":"query"},{"schema":{"type":"string","description":"IANA zone the days and buckets are read in; default UTC."},"required":false,"description":"IANA zone the days and buckets are read in; default UTC.","name":"tz","in":"query"},{"schema":{"type":"string","enum":["day","hour"],"description":"Bucket width; default day."},"required":false,"description":"Bucket width; default day.","name":"bucket","in":"query"},{"schema":{"type":"string","enum":["none","key","lane","role","session","model"],"description":"Split dimension; default none."},"required":false,"description":"Split dimension; default none.","name":"group","in":"query"},{"schema":{"type":"string","description":"Only rows from this key id."},"required":false,"description":"Only rows from this key id.","name":"key","in":"query"},{"schema":{"type":"string","description":"Only rows on this lane."},"required":false,"description":"Only rows on this lane.","name":"lane","in":"query"},{"schema":{"type":"string","description":"Only rows with this agent role."},"required":false,"description":"Only rows with this agent role.","name":"role","in":"query"},{"schema":{"type":"string","description":"Only rows in this session."},"required":false,"description":"Only rows in this session.","name":"session","in":"query"}],"responses":{"200":{"description":"Buckets, groups and totals.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageBreakdown"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/v1/usage/export":{"get":{"operationId":"exportUsage","summary":"Export usage rows","description":"The usage rows as a CSV (default), JSON or newline-delimited JSON attachment.","tags":["Usage & spend"],"security":[{"callerKey":["usage:read"]},{"apiKeyHeader":["usage:read"]},{"session":[]}],"x-superbot-scopes":["usage:read"],"parameters":[{"schema":{"type":"string","format":"date","description":"YYYY-MM-DD; default 30 days before `to`."},"required":false,"description":"YYYY-MM-DD; default 30 days before `to`.","name":"from","in":"query"},{"schema":{"type":"string","format":"date","description":"YYYY-MM-DD; default today (UTC)."},"required":false,"description":"YYYY-MM-DD; default today (UTC).","name":"to","in":"query"},{"schema":{"type":"string","enum":["csv","json","ndjson"],"description":"Attachment format; default csv."},"required":false,"description":"Attachment format; default csv.","name":"format","in":"query"},{"schema":{"type":"string","description":"IANA zone the days and buckets are read in; default UTC."},"required":false,"description":"IANA zone the days and buckets are read in; default UTC.","name":"tz","in":"query"},{"schema":{"type":"string","description":"Only rows from this key id."},"required":false,"description":"Only rows from this key id.","name":"key","in":"query"},{"schema":{"type":"string","description":"Only rows on this lane."},"required":false,"description":"Only rows on this lane.","name":"lane","in":"query"},{"schema":{"type":"string","description":"Only rows with this agent role."},"required":false,"description":"Only rows with this agent role.","name":"role","in":"query"},{"schema":{"type":"string","description":"Only rows in this session."},"required":false,"description":"Only rows in this session.","name":"session","in":"query"}],"responses":{"200":{"description":"The rows, as an attachment.","content":{"text/csv":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{},"additionalProperties":{}}}},"application/x-ndjson":{"schema":{"type":"string","description":"One JSON row object per line."}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/v1/credits":{"get":{"operationId":"getCredits","summary":"Get the credit balance","description":"The credit balance, the period meter and the plan.","tags":["Usage & spend"],"security":[{"callerKey":["billing:read"]},{"apiKeyHeader":["billing:read"]},{"session":[]}],"x-superbot-scopes":["billing:read"],"responses":{"200":{"description":"The balance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Credits"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/v1/spend":{"get":{"operationId":"getSpend","summary":"Get AI spend across apps","description":"AI spend across every app on the account over a window, by provider and day.","tags":["Usage & spend"],"security":[{"callerKey":["usage:read"]},{"apiKeyHeader":["usage:read"]},{"session":[]}],"x-superbot-scopes":["usage:read"],"parameters":[{"schema":{"type":"string","enum":["30d","90d","month","custom"],"description":"Window; default 30d."},"required":false,"description":"Window; default 30d.","name":"range","in":"query"},{"schema":{"type":"string","format":"date","description":"YYYY-MM-DD, with range=custom."},"required":false,"description":"YYYY-MM-DD, with range=custom.","name":"from","in":"query"},{"schema":{"type":"string","format":"date","description":"YYYY-MM-DD, with range=custom."},"required":false,"description":"YYYY-MM-DD, with range=custom.","name":"to","in":"query"}],"responses":{"200":{"description":"The spend report.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Spend"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/v1/keys":{"get":{"operationId":"listKeys","summary":"List caller keys","description":"Every caller key on the account, revoked ones included. Never the hash. A caller key reads the list without `person_email`, `prompt_history` and `person_limit_usd`, which are the account owner's; a person key lists only its own person's keys.","tags":["Keys"],"security":[{"callerKey":["keys:read"]},{"apiKeyHeader":["keys:read"]},{"session":[]}],"x-superbot-scopes":["keys:read"],"responses":{"200":{"description":"The keys.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallerKeyList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"operationId":"createKey","summary":"Create a caller key","description":"Mint a key. The plaintext is returned once. A caller key can only mint keys within its own reach: no scope, route, cap or model it does not hold. With `person` the key is minted for someone else and billed to you: the row carries `person_id`, `person_name` and the rest, and `name` defaults to the person's name. A bad `person` answers 400 `invalid_person`. Only the account owner (a signed-in session, a device or the account key) mints a key for a person: a caller key that sends `person` answers 403 `caller_key_forbidden`, and so does a person key minting any key. A person key minted with no `scopes` or `preset` holds `gateway:invoke` alone. A paused caller key answers 403 `key_paused`.","tags":["Keys"],"security":[{"callerKey":["keys:write"]},{"apiKeyHeader":["keys:write"]},{"session":[]}],"x-superbot-scopes":["keys:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateKeyRequest"}}}},"responses":{"201":{"description":"The new key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedKey"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/v1/keys/whoami":{"get":{"operationId":"getCurrentKey","summary":"Get the calling key","description":"The calling caller key’s own row and effective scopes, and its own metered usage in three windows (`usage`). A person key’s fields ride on `row`. Caller keys only; a session gets 403 caller_key_required. A revoked key gets 403 revoked_key, a paused one 403 key_paused.","tags":["Keys"],"security":[{"callerKey":[]},{"apiKeyHeader":[]}],"x-superbot-scopes":[],"responses":{"200":{"description":"The key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CurrentKey"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/keys/{id}":{"patch":{"operationId":"updateKey","summary":"Update a caller key","description":"Edit a key’s name, route, mode, caps, models, default model or scopes. A bad `default_model` answers 400 `invalid_default_model`. On a person key, `person_name`, `person_email`, `person_group`, `prompt_history` and `paused_at` edit the person and are written to every live key of that person; on any other key they answer 400 `not_a_person_key`, and an invalid value answers 400 `invalid_person`. A person key is edited by the account owner only, and a person field is changed by the account owner only: a caller key that tries either answers 403 `caller_key_forbidden`. A person key cannot be renamed `account`. A paused caller key answers 403 `key_paused`.","tags":["Keys"],"security":[{"callerKey":["keys:write"]},{"apiKeyHeader":["keys:write"]},{"session":[]}],"x-superbot-scopes":["keys:write"],"parameters":[{"schema":{"type":"string","example":"ck_9f2c41d0"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKeyRequest"}}}},"responses":{"200":{"description":"The edited key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatedKey"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"revokeKey","summary":"Revoke a caller key","description":"Revoke a key. Revoking an already-revoked key is a no-op (`already: true`). A person key is revoked by the account owner only; a caller key that tries answers 403 `caller_key_forbidden`.","tags":["Keys"],"security":[{"callerKey":["keys:write"]},{"apiKeyHeader":["keys:write"]},{"session":[]}],"x-superbot-scopes":["keys:write"],"parameters":[{"schema":{"type":"string","example":"ck_9f2c41d0"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokedKey"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/keys/{id}/rotate":{"post":{"operationId":"rotateKey","summary":"Rotate a caller key","description":"Replace a key with a new one of the same shape (name, scopes, route, mode, caps, models, pins, aliases, default model, incognito, the person it is for, the device that minted it) and revoke the old one. The new key is minted first and the old one revoked after, so a failure never leaves the account without a working key. The reply carries the new key in plaintext once (`key`), its row, and `revoked`, the id of the key revoked (`null` if that revoke failed after the mint: the new key is live, so revoke the old one with `DELETE /v1/keys/{id}`). No body. A key that is revoked already answers 409 `revoked`; an id this account does not hold answers 404 `not_found`; a team key answers 400 `team_key` (rotate it on the team pane). A person key is rotated by the account owner only; a caller key that tries answers 403 `caller_key_forbidden`. The new key has made no calls yet, so it lists under Zapier or n8n again with its first call.","tags":["Keys"],"security":[{"callerKey":["keys:write"]},{"apiKeyHeader":["keys:write"]},{"session":[]}],"x-superbot-scopes":["keys:write"],"parameters":[{"schema":{"type":"string","example":"ck_9f2c41d0"},"required":true,"name":"id","in":"path"}],"responses":{"201":{"description":"The new key, once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotatedKey"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/v1/upstreams":{"get":{"operationId":"listUpstreams","summary":"List custom endpoints","description":"Every custom endpoint on the account. Never the API key; header values are redacted for caller keys.","tags":["Endpoints"],"security":[{"callerKey":["endpoints:read"]},{"apiKeyHeader":["endpoints:read"]},{"session":[]}],"x-superbot-scopes":["endpoints:read"],"responses":{"200":{"description":"The endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpstreamList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"operationId":"createUpstream","summary":"Add a custom endpoint","description":"Add an OpenAI- or Anthropic-compatible endpoint and probe it. A failed probe still saves.","tags":["Endpoints"],"security":[{"callerKey":["endpoints:write"]},{"apiKeyHeader":["endpoints:write"]},{"session":[]}],"x-superbot-scopes":["endpoints:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUpstreamRequest"}}}},"responses":{"201":{"description":"The saved endpoint and its probe.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpstreamWithProbe"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/v1/upstreams/{slug}":{"patch":{"operationId":"updateUpstream","summary":"Update a custom endpoint","description":"Edit label, dialect, key, models or model names; re-probes when the dial changed.","tags":["Endpoints"],"security":[{"callerKey":["endpoints:write"]},{"apiKeyHeader":["endpoints:write"]},{"session":[]}],"x-superbot-scopes":["endpoints:write"],"parameters":[{"schema":{"type":"string","example":"openrouter"},"required":true,"name":"slug","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUpstreamRequest"}}}},"responses":{"200":{"description":"The edited endpoint and its last probe.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpstreamWithProbe"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"deleteUpstream","summary":"Remove a custom endpoint","description":"Remove the endpoint and its stored key.","tags":["Endpoints"],"security":[{"callerKey":["endpoints:write"]},{"apiKeyHeader":["endpoints:write"]},{"session":[]}],"x-superbot-scopes":["endpoints:write"],"parameters":[{"schema":{"type":"string","example":"openrouter"},"required":true,"name":"slug","in":"path"}],"responses":{"204":{"description":"Removed."},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/upstreams/{slug}/probe":{"post":{"operationId":"probeUpstream","summary":"Re-probe a custom endpoint","description":"Dial the stored endpoint and fold what it lists into the row. A failed probe is a 200 whose report says so.","tags":["Endpoints"],"security":[{"callerKey":["endpoints:write"]},{"apiKeyHeader":["endpoints:write"]},{"session":[]}],"x-superbot-scopes":["endpoints:write"],"parameters":[{"schema":{"type":"string","example":"openrouter"},"required":true,"name":"slug","in":"path"}],"responses":{"200":{"description":"The endpoint and the probe.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpstreamWithProbe"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/aliases":{"get":{"operationId":"listAliases","summary":"List @mention aliases","description":"Your own aliases, the built-in ones, then the catalog; `available` says whether the vendor is linked.","tags":["Endpoints"],"security":[{"callerKey":["endpoints:read"]},{"apiKeyHeader":["endpoints:read"]},{"session":[]}],"x-superbot-scopes":["endpoints:read"],"responses":{"200":{"description":"The aliases.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Alias"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/v1/aliases/{token}":{"put":{"operationId":"setAlias","summary":"Set an @mention alias","description":"Create or overwrite one personal alias; every paired device picks it up.","tags":["Endpoints"],"security":[{"callerKey":["endpoints:write"]},{"apiKeyHeader":["endpoints:write"]},{"session":[]}],"x-superbot-scopes":["endpoints:write"],"parameters":[{"schema":{"type":"string","example":"claude"},"required":true,"name":"token","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetAliasRequest"}}}},"responses":{"200":{"description":"Saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AliasWrite"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"delete":{"operationId":"deleteAlias","summary":"Delete an @mention alias","description":"Delete one personal alias on every device.","tags":["Endpoints"],"security":[{"callerKey":["endpoints:write"]},{"apiKeyHeader":["endpoints:write"]},{"session":[]}],"x-superbot-scopes":["endpoints:write"],"parameters":[{"schema":{"type":"string","example":"claude"},"required":true,"name":"token","in":"path"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AliasWrite"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/v1/org/{id}/audit":{"get":{"operationId":"exportTeamAuditLog","summary":"Export a team’s audit log","description":"The team’s audit log, oldest first, as NDJSON (default) or CSV: who, on which device and through which agent, used which credential class for what, and the outcome. Rows are kept for a year. Owners and admins only; a member gets 403 and a caller outside the team 404. At most `limit` rows per request; when more remain, the `x-next-cursor` header carries the cursor for the next page. Columns, in CSV order: ts, org_id, actor_user_id, actor_email, device_id, agent, credential_class, credential_ref, action, target, outcome, request_id, ip, ua.","tags":["Teams"],"security":[{"callerKey":["teams:read"]},{"apiKeyHeader":["teams:read"]},{"session":[]}],"x-superbot-scopes":["teams:read"],"parameters":[{"schema":{"type":"string","description":"The team id (`org_…`)."},"required":true,"description":"The team id (`org_…`).","name":"id","in":"path"},{"schema":{"type":"string","enum":["ndjson","csv"],"description":"Attachment format; default ndjson."},"required":false,"description":"Attachment format; default ndjson.","name":"format","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Rows at or after this time; default a year ago."},"required":false,"description":"Rows at or after this time; default a year ago.","name":"since","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Rows before this time; default now."},"required":false,"description":"Rows before this time; default now.","name":"until","in":"query"},{"schema":{"type":"string","description":"The previous page’s `x-next-cursor`."},"required":false,"description":"The previous page’s `x-next-cursor`.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"description":"Rows per page; default 1000, and anything above 5000 is read as 5000."},"required":false,"description":"Rows per page; default 1000, and anything above 5000 is read as 5000.","name":"limit","in":"query"}],"responses":{"200":{"description":"The rows, as an attachment.","headers":{"x-next-cursor":{"description":"Present when more rows remain: pass it back as `cursor`.","schema":{"type":"string"}},"x-audit-rows":{"description":"How many rows this page holds.","schema":{"type":"string"}}},"content":{"application/x-ndjson":{"schema":{"type":"string","description":"One row object per line."}},"text/csv":{"schema":{"type":"string","description":"A header line, then one row per line."}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"503":{"description":"The audit store is unavailable; retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/teams":{"get":{"operationId":"listTeams","summary":"List teams","description":"Every team the caller is a live member of, oldest first. A team key sees only its own team.","tags":["Teams"],"security":[{"callerKey":["teams:read"]},{"apiKeyHeader":["teams:read"]},{"session":[]}],"x-superbot-scopes":["teams:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Items per page, 1-100.","example":20},"required":false,"description":"Items per page, 1-100.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Return the page after this resource id (the previous page’s `last_id`)."},"required":false,"description":"Return the page after this resource id (the previous page’s `last_id`).","name":"after_id","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Return the page before this resource id (the next page’s `first_id`)."},"required":false,"description":"Return the page before this resource id (the next page’s `first_id`).","name":"before_id","in":"query"}],"responses":{"200":{"description":"One page of teams.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamList"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"operationId":"createTeam","summary":"Create a team","description":"Create a team with the caller as its one owner. The owner’s Helper sets up the team key when it next syncs.","tags":["Teams"],"security":[{"callerKey":["teams:write"]},{"apiKeyHeader":["teams:write"]},{"session":[]}],"x-superbot-scopes":["teams:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTeamRequest"}}}},"responses":{"201":{"description":"The new team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Team"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/v1/teams/{team_id}":{"get":{"operationId":"getTeam","summary":"Get a team","description":"One team the caller is a member of, with the caller’s own role.","tags":["Teams"],"security":[{"callerKey":["teams:read"]},{"apiKeyHeader":["teams:read"]},{"session":[]}],"x-superbot-scopes":["teams:read"],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The team id.","example":"org_7c1e…"},"required":true,"description":"The team id.","name":"team_id","in":"path"}],"responses":{"200":{"description":"The team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Team"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"operationId":"updateTeam","summary":"Update a team","description":"Rename a team or change its sharing settings. Only the fields sent change. Admins and owners only.","tags":["Teams"],"security":[{"callerKey":["teams:write"]},{"apiKeyHeader":["teams:write"]},{"session":[]}],"x-superbot-scopes":["teams:write"],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The team id.","example":"org_7c1e…"},"required":true,"description":"The team id.","name":"team_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTeamRequest"}}}},"responses":{"200":{"description":"The updated team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Team"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"deleteTeam","summary":"Delete a team","description":"Delete a team and every membership in it. Owners only. This cannot be undone.","tags":["Teams"],"security":[{"callerKey":["teams:write"]},{"apiKeyHeader":["teams:write"]},{"session":[]}],"x-superbot-scopes":["teams:write"],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The team id.","example":"org_7c1e…"},"required":true,"description":"The team id.","name":"team_id","in":"path"}],"responses":{"200":{"description":"The team is gone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedTeam"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/teams/{team_id}/members":{"get":{"operationId":"listTeamMembers","summary":"List team members","description":"The team’s live members, paged by user id in join order.","tags":["Teams"],"security":[{"callerKey":["teams:read"]},{"apiKeyHeader":["teams:read"]},{"session":[]}],"x-superbot-scopes":["teams:read"],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The team id.","example":"org_7c1e…"},"required":true,"description":"The team id.","name":"team_id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Items per page, 1-100.","example":20},"required":false,"description":"Items per page, 1-100.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Return the page after this resource id (the previous page’s `last_id`)."},"required":false,"description":"Return the page after this resource id (the previous page’s `last_id`).","name":"after_id","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Return the page before this resource id (the next page’s `first_id`)."},"required":false,"description":"Return the page before this resource id (the next page’s `first_id`).","name":"before_id","in":"query"}],"responses":{"200":{"description":"One page of members.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberList"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/teams/{team_id}/members/{user_id}":{"patch":{"operationId":"updateTeamMember","summary":"Change a member’s role","description":"Set a member’s role. You can only grant a role below your own, to a member below your own. Ownership never moves here.","tags":["Teams"],"security":[{"callerKey":["teams:write"]},{"apiKeyHeader":["teams:write"]},{"session":[]}],"x-superbot-scopes":["teams:write"],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The team id.","example":"org_7c1e…"},"required":true,"description":"The team id.","name":"team_id","in":"path"},{"schema":{"type":"string","minLength":1,"description":"The member’s account id."},"required":true,"description":"The member’s account id.","name":"user_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTeamMemberRequest"}}}},"responses":{"200":{"description":"The member.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMember"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"removeTeamMember","summary":"Remove a team member","description":"Remove a member. Admins remove members below them; owners remove anyone except the last owner (409 last_owner).","tags":["Teams"],"security":[{"callerKey":["teams:write"]},{"apiKeyHeader":["teams:write"]},{"session":[]}],"x-superbot-scopes":["teams:write"],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The team id.","example":"org_7c1e…"},"required":true,"description":"The team id.","name":"team_id","in":"path"},{"schema":{"type":"string","minLength":1,"description":"The member’s account id."},"required":true,"description":"The member’s account id.","name":"user_id","in":"path"}],"responses":{"200":{"description":"The member is removed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemovedTeamMember"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/v1/teams/{team_id}/invites":{"get":{"operationId":"listTeamInvites","summary":"List pending team invites","description":"Invites not yet accepted, revoked or expired, paged by invite code in the order they were sent. Admins and owners only.","tags":["Teams"],"security":[{"callerKey":["teams:read"]},{"apiKeyHeader":["teams:read"]},{"session":[]}],"x-superbot-scopes":["teams:read"],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The team id.","example":"org_7c1e…"},"required":true,"description":"The team id.","name":"team_id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Items per page, 1-100.","example":20},"required":false,"description":"Items per page, 1-100.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Return the page after this resource id (the previous page’s `last_id`)."},"required":false,"description":"Return the page after this resource id (the previous page’s `last_id`).","name":"after_id","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Return the page before this resource id (the next page’s `first_id`)."},"required":false,"description":"Return the page before this resource id (the next page’s `first_id`).","name":"before_id","in":"query"}],"responses":{"200":{"description":"One page of invites.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInviteList"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"operationId":"createTeamInvite","summary":"Invite someone to a team","description":"Email an invite for a role below your own (default member). A pending invite to the same address is replaced. Invites expire after 7 days.","tags":["Teams"],"security":[{"callerKey":["teams:write"]},{"apiKeyHeader":["teams:write"]},{"session":[]}],"x-superbot-scopes":["teams:write"],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The team id.","example":"org_7c1e…"},"required":true,"description":"The team id.","name":"team_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTeamInviteRequest"}}}},"responses":{"201":{"description":"The invite, already mailed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvite"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/teams/{team_id}/invites/{code}":{"delete":{"operationId":"revokeTeamInvite","summary":"Revoke a team invite","description":"Revoke an invite. Its link stops working at once.","tags":["Teams"],"security":[{"callerKey":["teams:write"]},{"apiKeyHeader":["teams:write"]},{"session":[]}],"x-superbot-scopes":["teams:write"],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The team id.","example":"org_7c1e…"},"required":true,"description":"The team id.","name":"team_id","in":"path"},{"schema":{"type":"string","minLength":1,"description":"The invite code.","example":"inv_…"},"required":true,"description":"The invite code.","name":"code","in":"path"}],"responses":{"200":{"description":"The invite is revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokedTeamInvite"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/teams/{team_id}/invites/{code}/resend":{"post":{"operationId":"resendTeamInvite","summary":"Resend a team invite","description":"Replace a pending invite with a fresh code and mail it again. The old link stops working.","tags":["Teams"],"security":[{"callerKey":["teams:write"]},{"apiKeyHeader":["teams:write"]},{"session":[]}],"x-superbot-scopes":["teams:write"],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The team id.","example":"org_7c1e…"},"required":true,"description":"The team id.","name":"team_id","in":"path"},{"schema":{"type":"string","minLength":1,"description":"The invite code.","example":"inv_…"},"required":true,"description":"The invite code.","name":"code","in":"path"}],"responses":{"200":{"description":"The new invite, already mailed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvite"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/v1/team_invites/{code}/accept":{"post":{"operationId":"acceptTeamInvite","summary":"Accept a team invite","description":"Join the team an invite names. The account’s email must match the invite; an account with no email adds one in Sign-in methods first (`invite_needs_email`). `share` chooses what you pool into the team; MCP servers stay unshared unless you set `mcp`.","tags":["Teams"],"security":[{"callerKey":["teams:write"]},{"apiKeyHeader":["teams:write"]},{"session":[]}],"x-superbot-scopes":["teams:write"],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The invite code.","example":"inv_…"},"required":true,"description":"The invite code.","name":"code","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptTeamInviteRequest"}}}},"responses":{"200":{"description":"The team you joined.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Team"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/v1/devices":{"get":{"operationId":"listDevices","summary":"List devices","description":"The devices paired to this account, oldest first, paged by device id. `online` filters on presence (seen within the last two minutes). Revoked devices are not listed.","tags":["Devices"],"security":[{"callerKey":["devices:read"]},{"apiKeyHeader":["devices:read"]},{"session":[]}],"x-superbot-scopes":["devices:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Items per page, 1-100.","example":20},"required":false,"description":"Items per page, 1-100.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Return the page after this resource id (the previous page’s `last_id`)."},"required":false,"description":"Return the page after this resource id (the previous page’s `last_id`).","name":"after_id","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Return the page before this resource id (the next page’s `first_id`)."},"required":false,"description":"Return the page before this resource id (the next page’s `first_id`).","name":"before_id","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Only devices that are (`true`) or are not (`false`) online now."},"required":false,"description":"Only devices that are (`true`) or are not (`false`) online now.","name":"online","in":"query"}],"responses":{"200":{"description":"A page of devices.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceList"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/devices/{device_id}":{"get":{"operationId":"getDevice","summary":"Get a device","description":"One device, with its live capabilities when it is connected.","tags":["Devices"],"security":[{"callerKey":["devices:read"]},{"apiKeyHeader":["devices:read"]},{"session":[]}],"x-superbot-scopes":["devices:read"],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"The device id (a Device `id`)."},"required":true,"description":"The device id (a Device `id`).","name":"device_id","in":"path"}],"responses":{"200":{"description":"The device.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Device"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"operationId":"updateDevice","summary":"Rename a device","description":"Set the device label. The label survives later activity from the device.","tags":["Devices"],"security":[{"callerKey":["devices:write"]},{"apiKeyHeader":["devices:write"]},{"session":[]}],"x-superbot-scopes":["devices:write"],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"The device id (a Device `id`)."},"required":true,"description":"The device id (a Device `id`).","name":"device_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","minLength":1,"description":"The new label, 1-64 printable characters (trimmed).","example":"Studio Mac"}},"required":["label"],"additionalProperties":false}}}},"responses":{"200":{"description":"The renamed device.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Device"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"operationId":"deleteDevice","summary":"Unlink a device","description":"Sign the device out: its tokens and the caller keys it minted are revoked. The caller's own device answers 409 `own_device` (sign out from that device instead).","tags":["Devices"],"security":[{"callerKey":["devices:write"]},{"apiKeyHeader":["devices:write"]},{"session":[]}],"x-superbot-scopes":["devices:write"],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"The device id (a Device `id`)."},"required":true,"description":"The device id (a Device `id`).","name":"device_id","in":"path"}],"responses":{"200":{"description":"The device was unlinked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedDevice"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/usage/report":{"get":{"operationId":"getUsageReport","summary":"Get a usage report","description":"The account’s usage across every key in hourly or daily UTC buckets, grouped by any mix of key, model, lane, role, session and team, and narrowed by any filter. A person key reads its own person’s usage here, never the account’s.","tags":["Usage & spend"],"security":[{"callerKey":["usage:read"]},{"apiKeyHeader":["usage:read"]},{"session":[]}],"x-superbot-scopes":["usage:read"],"parameters":[{"schema":{"type":"string","format":"date-time","description":"RFC 3339 start, floored to the bucket width. Default: 7 days before `ending_at`.","example":"2026-09-01T00:00:00Z"},"required":false,"description":"RFC 3339 start, floored to the bucket width. Default: 7 days before `ending_at`.","name":"starting_at","in":"query"},{"schema":{"type":"string","format":"date-time","description":"RFC 3339 end (exclusive), ceiled to the bucket width. Default: the end of the current bucket. At most 92 days after `starting_at`."},"required":false,"description":"RFC 3339 end (exclusive), ceiled to the bucket width. Default: the end of the current bucket. At most 92 days after `starting_at`.","name":"ending_at","in":"query"},{"schema":{"type":"string","enum":["1h","1d"],"description":"Bucket width; default 1d."},"required":false,"description":"Bucket width; default 1d.","name":"bucket_width","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Split each bucket by these dimensions: api_key_id, model, lane, role, session_id, team_id. Repeat the parameter or pass a comma list."},"required":false,"description":"Split each bucket by these dimensions: api_key_id, model, lane, role, session_id, team_id. Repeat the parameter or pass a comma list.","name":"group_by","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only usage from these caller key ids. Repeat the parameter or pass a comma list."},"required":false,"description":"Only usage from these caller key ids. Repeat the parameter or pass a comma list.","name":"api_key_ids","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only usage on these model ids. Repeat the parameter or pass a comma list."},"required":false,"description":"Only usage on these model ids. Repeat the parameter or pass a comma list.","name":"models","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only usage on these lanes: credits, caller_key, byo. Repeat the parameter or pass a comma list."},"required":false,"description":"Only usage on these lanes: credits, caller_key, byo. Repeat the parameter or pass a comma list.","name":"lanes","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only usage with these agent roles (chat for a plain turn). Repeat the parameter or pass a comma list."},"required":false,"description":"Only usage with these agent roles (chat for a plain turn). Repeat the parameter or pass a comma list.","name":"roles","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only usage inside these agent runs. Repeat the parameter or pass a comma list."},"required":false,"description":"Only usage inside these agent runs. Repeat the parameter or pass a comma list.","name":"session_ids","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only usage from keys scoped to these teams. Repeat the parameter or pass a comma list."},"required":false,"description":"Only usage from keys scoped to these teams. Repeat the parameter or pass a comma list.","name":"team_ids","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":168,"description":"Buckets per page. 1h: default 24, max 168. 1d: default 7, max 31."},"required":false,"description":"Buckets per page. 1h: default 24, max 168. 1d: default 7, max 31.","name":"limit","in":"query"},{"schema":{"type":"string","description":"The previous response’s `next_page`. Repeat group_by and the filters with it."},"required":false,"description":"The previous response’s `next_page`. Repeat group_by and the filters with it.","name":"page","in":"query"}],"responses":{"200":{"description":"One page of buckets.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageReport"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"description":"The account store is not ready; retry later."}}}},"/v1/runs":{"post":{"operationId":"createRun","summary":"Start a cloud run","description":"Queue a cloud agent run on a project. Refusals: 400 `invalid_mode`, `invalid_landing`, `invalid_prompt`, `missing_space`, `invalid_webhook_url`; 429 `key_run_limit` (this key, default 5 queued or running), with `Retry-After`. Asks the run raises are answered deny, since a key cannot answer them.","tags":["Runs"],"security":[{"callerKey":["runs:write"]},{"apiKeyHeader":["runs:write"]},{"session":[]}],"x-superbot-scopes":["runs:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"project":{"type":"string","maxLength":200,"description":"The project to run on.","example":"prj_7f3a"},"prompt":{"type":"string","maxLength":100000,"description":"What the agent should do.","example":"Fix the flaky login test."},"mode":{"type":"string","description":"One of `agent`, `plan`, `debug`. Default `agent`."},"landing":{"type":"string","description":"One of `main`, `pr`. Default `main`."},"budget":{"type":"object","properties":{"minutes":{"type":"number","exclusiveMinimum":0},"usd":{"type":"number","exclusiveMinimum":0},"legs":{"type":"integer","exclusiveMinimum":0}},"additionalProperties":false,"description":"Caps for this run. Absent fields fall back to your saved defaults."},"webhook_url":{"type":"string","description":"A public https URL that receives a signed `run.settled` POST when the run settles."}},"required":["project","prompt"],"additionalProperties":false}}}},"responses":{"201":{"description":"The queued run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedRun"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"get":{"operationId":"listRuns","summary":"List cloud runs","description":"This account’s cloud runs from every source, oldest first, paged by run id.","tags":["Runs"],"security":[{"callerKey":["runs:read"]},{"apiKeyHeader":["runs:read"]},{"session":[]}],"x-superbot-scopes":["runs:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Items per page, 1-100.","example":20},"required":false,"description":"Items per page, 1-100.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Return the page after this resource id (the previous page’s `last_id`)."},"required":false,"description":"Return the page after this resource id (the previous page’s `last_id`).","name":"after_id","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Return the page before this resource id (the next page’s `first_id`)."},"required":false,"description":"Return the page before this resource id (the next page’s `first_id`).","name":"before_id","in":"query"},{"schema":{"type":"string","enum":["queued","running","done","failed","needs_merge","cancelled"],"description":"Only runs in this status."},"required":false,"description":"Only runs in this status.","name":"status","in":"query"},{"schema":{"type":"string","enum":["app","api","cli","routine","slack","linear","jira","github"],"description":"Only runs started by this source."},"required":false,"description":"Only runs started by this source.","name":"source","in":"query"}],"responses":{"200":{"description":"A page of runs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunList"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/runs/projects":{"get":{"operationId":"listRunProjects","summary":"Find the project for a repository","description":"Your projects whose linked repository is `repo`, compared after normalising the URL (scheme, `git@host:` form, a trailing `.git` and case do not matter). Pass a returned `id` as `project` to createRun. Only `id` and `name` are returned. An empty list means no project is linked to that repository. Refusal: 400 `invalid_repo`.","tags":["Runs"],"security":[{"callerKey":["runs:read"]},{"apiKeyHeader":["runs:read"]},{"session":[]}],"x-superbot-scopes":["runs:read"],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":2000,"description":"The repository URL, on any git host: `https://example.com/o/r`, `ssh://git@example.com/o/r.git` or `git@example.com:o/r.git` all match the same project.","example":"https://example.com/acme/app"},"required":true,"description":"The repository URL, on any git host: `https://example.com/o/r`, `ssh://git@example.com/o/r.git` or `git@example.com:o/r.git` all match the same project.","name":"repo","in":"query"}],"responses":{"200":{"description":"The matching projects, possibly none.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunProjectList"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/runs/{run_id}":{"get":{"operationId":"getRun","summary":"Get a cloud run","description":"One run as it stands now.","tags":["Runs"],"security":[{"callerKey":["runs:read"]},{"apiKeyHeader":["runs:read"]},{"session":[]}],"x-superbot-scopes":["runs:read"],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"The run id (a Run `id`)."},"required":true,"description":"The run id (a Run `id`).","name":"run_id","in":"path"}],"responses":{"200":{"description":"The run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/runs/{run_id}/events":{"get":{"operationId":"listRunEvents","summary":"Follow a run’s events","description":"With `Accept: text/event-stream`, server-sent events (`id` is the event `seq`; reconnect with `Last-Event-ID` to resume); the stream ends once the run is final. Otherwise JSON: the events after `after`, long-polled up to `wait` seconds.","tags":["Runs"],"security":[{"callerKey":["runs:read"]},{"apiKeyHeader":["runs:read"]},{"session":[]}],"x-superbot-scopes":["runs:read"],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"The run id (a Run `id`)."},"required":true,"description":"The run id (a Run `id`).","name":"run_id","in":"path"},{"schema":{"type":"string","description":"Only events with a greater `seq`. `Last-Event-ID` wins when both are sent."},"required":false,"description":"Only events with a greater `seq`. `Last-Event-ID` wins when both are sent.","name":"after","in":"query"},{"schema":{"type":"string","description":"Long-poll: hold the request up to this many seconds (max 25) for a new event. JSON replies only."},"required":false,"description":"Long-poll: hold the request up to this many seconds (max 25) for a new event. JSON replies only.","name":"wait","in":"query"}],"responses":{"200":{"description":"The events.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunEventList"}},"text/event-stream":{"schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/runs/{run_id}/cancel":{"post":{"operationId":"cancelRun","summary":"Cancel a cloud run","description":"Stop the run. A run that already settled is returned as it is.","tags":["Runs"],"security":[{"callerKey":["runs:write"]},{"apiKeyHeader":["runs:write"]},{"session":[]}],"x-superbot-scopes":["runs:write"],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"The run id (a Run `id`)."},"required":true,"description":"The run id (a Run `id`).","name":"run_id","in":"path"}],"responses":{"200":{"description":"The run after the cancel.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/runs/{run_id}/messages":{"post":{"operationId":"sendRunMessage","summary":"Steer a running cloud run","description":"Add a note to a run that is queued or running. The run is not restarted: it reads the note at its next step boundary (never mid-step) and carries on with it as a note from you. Notes are applied oldest first. Refusals: 409 `run_not_active` (the run settled); 400 `invalid_note` or `note_too_long` (over 8192 bytes); 429 `too_many_notes` (20 notes already waiting), with `Retry-After`. The run's events record `note_queued` and `note_delivered` with the note id and length, never its text.","tags":["Runs"],"security":[{"callerKey":["runs:write"]},{"apiKeyHeader":["runs:write"]},{"session":[]}],"x-superbot-scopes":["runs:write"],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"The run id (a Run `id`)."},"required":true,"description":"The run id (a Run `id`).","name":"run_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","maxLength":100000,"description":"The note, up to 8192 bytes of UTF-8.","example":"Skip the migration for now and focus on the failing test."}},"required":["text"],"additionalProperties":false}}}},"responses":{"202":{"description":"The note, queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunNote"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/docs/services/{service_id}.json":{"get":{"operationId":"getServiceDocument","summary":"Get a service’s OpenAPI document","description":"One shipped service’s learned endpoints as an OpenAPI 3.1 document (`x-path-templates`, `x-superbot-replay`): endpoint shapes, header rule names and provenance, never an example value or a credential.","tags":["Endpoints"],"security":[{"callerKey":[]},{"apiKeyHeader":[]},{"session":[]},{}],"x-superbot-scopes":[],"parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"string"},"description":"The service id, e.g. `doordash`."}],"responses":{"200":{"description":"The service as OpenAPI 3.1.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"An OpenAPI 3.1 document."}}}},"404":{"$ref":"#/components/responses/NotFound"}}}}},"webhooks":{}}