{"openapi":"3.1.0","info":{"title":"Twigg customer API","description":"Customer API operations. Prose documentation: https://twigg.ai/docs. Machine-readable index: https://twigg.ai/llms.txt.","version":"v1"},"servers":[{"url":"https://api.twigg.ai"}],"paths":{"/":{"get":{"tags":["Discovery"],"summary":"Public links for a client starting with only the API base URL.","operationId":"discovery","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Discovery"}}}}},"security":[]}},"/api/v1/chats":{"get":{"tags":["customer-api","Chats"],"summary":"List chats","description":"List chats newest first. Use after_id or before_id to page; they are mutually exclusive. Pass include=usage to add each chat's cost and token totals; they are not computed otherwise. Unknown query parameters are ignored.","operationId":"listChats","parameters":[{"name":"namespace","in":"query","description":"Scope to a namespace **and everything beneath it**. `acme/proj-7`\nreturns that scope's chats plus `acme/proj-7/user-99`'s and deeper.\nAbsent lists the whole organisation.\n\nA namespace with no chats is not an error — there is no registry, so\n\"empty\" and \"never used\" are the same state and both return `[]`.","required":false,"schema":{"$ref":"#/components/schemas/Namespace"}},{"name":"after_id","in":"query","description":"Page **older** than this id. Listings run newest-first, so \"after\" means\nfurther down the list, which is further back in time.","required":false,"schema":{"$ref":"#/components/schemas/ChatId"}},{"name":"before_id","in":"query","description":"Page **newer** than this id.","required":false,"schema":{"$ref":"#/components/schemas/ChatId"}},{"name":"limit","in":"query","description":"1–100. Out-of-range values are clamped.","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"include","in":"query","description":"`usage` adds each chat's cost and token totals. Left out, they are not\ncomputed at all.","required":false,"schema":{"type":"string","description":"The chat `include` parameter's vocabulary.","enum":["usage"]}}],"responses":{"200":{"description":"List chats","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatPage"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]},"post":{"tags":["customer-api","Chats"],"summary":"Create a chat","description":"Create an empty chat in the authenticated organisation. All request fields are optional. An external_id another live chat in the organisation already holds returns 409 external_id_taken; use PUT /api/v1/chats/external/{external_id} to create or get by external id.","operationId":"createChat","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateChatRequest"}}},"required":true},"responses":{"201":{"description":"Create a chat","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCreated"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"413":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]},"delete":{"tags":["customer-api","Chats"],"summary":"Delete chats under a namespace prefix","description":"Delete every chat in namespace_prefix and every namespace beneath it, exactly as DELETE /api/v1/chats/{chat_id} deletes one: turns in progress are aborted, content is unrecoverable once this returns, and stored objects are removed in the background. Returns how many chats were deleted; a prefix with no live chats returns 0. Pair it with DELETE /api/v1/config?namespace_prefix= to remove the subtree's configuration too.","operationId":"deleteChatsByNamespace","parameters":[{"name":"namespace_prefix","in":"query","description":"Deletes the chats in this namespace and every namespace beneath it, by\npath segment: `swarm/run-abc` covers `swarm/run-abc/agent-17` but not\n`swarm/run-abcd`.","required":true,"schema":{"$ref":"#/components/schemas/Namespace"}}],"responses":{"200":{"description":"Deleted chat count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatsDeleted"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/chats/external/{external_id}":{"get":{"tags":["customer-api","Chats"],"summary":"Get a chat by external id","description":"Fetch the chat holding this external id. Unknown ids, deleted chats and another organisation's ids all return 404. Pass include=usage to add the chat's cost and token totals.","operationId":"getChatByExternalId","parameters":[{"name":"external_id","in":"path","description":"Your own identifier for the chat","required":true,"schema":{"$ref":"#/components/schemas/ExternalChatId"}},{"name":"include","in":"query","description":"`usage` adds the chat's cost and token totals.","required":false,"schema":{"type":"string","description":"The chat `include` parameter's vocabulary.","enum":["usage"]}}],"responses":{"200":{"description":"Get a chat by external id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatSummary"}}}},"400":{"description":"A malformed external id in the path","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]},"put":{"tags":["customer-api","Chats"],"summary":"Create or get a chat by external id","description":"Return the chat holding this external id, creating it from the body if there is none. 201 means it was created, 200 that it already existed. On an existing chat the body is ignored, except that a namespace you send that differs from the chat's (including null for a namespaced chat) returns 409 external_id_namespace_mismatch; leaving namespace out skips the check. External ids are unique per organisation and case-sensitive; percent-encode them in the path.","operationId":"openChatByExternalId","parameters":[{"name":"external_id","in":"path","description":"Your own identifier for the chat","required":true,"schema":{"$ref":"#/components/schemas/ExternalChatId"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenChatRequest"}}},"required":true},"responses":{"200":{"description":"Already existed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatSummary"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatSummary"}}}},"400":{"description":"A malformed external id in the path","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"413":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]},"delete":{"tags":["customer-api","Chats"],"summary":"Delete a chat by external id","description":"Delete the chat holding this external id. The external id is cleared from the chat and freed, so a later message to it starts a new chat. Repeating the deletion returns 404.","operationId":"deleteChatByExternalId","parameters":[{"name":"external_id","in":"path","description":"Your own identifier for the chat","required":true,"schema":{"$ref":"#/components/schemas/ExternalChatId"}}],"responses":{"204":{"description":"Delete a chat by external id"},"400":{"description":"A malformed external id in the path","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]},"patch":{"tags":["customer-api","Chats"],"summary":"Update a chat by external id","description":"The same as PATCH /api/v1/chats/{chat_id}, for the chat holding this external id. The external id itself cannot be changed.","operationId":"updateChatByExternalId","parameters":[{"name":"external_id","in":"path","description":"Your own identifier for the chat","required":true,"schema":{"$ref":"#/components/schemas/ExternalChatId"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateChatRequest"}}},"required":true},"responses":{"200":{"description":"The updated chat","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatSummary"}}}},"400":{"description":"A malformed external id in the path","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"413":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/chats/external/{external_id}/abort":{"post":{"tags":["customer-api","Responses"],"summary":"Abort the turn in progress by external id","description":"The same as POST /api/v1/chats/{chat_id}/abort, for the chat holding this external id.","operationId":"abortResponseByExternalId","parameters":[{"name":"external_id","in":"path","description":"Your own identifier for the chat","required":true,"schema":{"$ref":"#/components/schemas/ExternalChatId"}},{"name":"run_id","in":"query","description":"The run you mean to stop: the `run_id` from the stream's `run` event.\nOptional. When given, nothing else is stopped, so an abort that arrives\nlate cannot stop the chat's *next* turn by mistake.","required":false,"schema":{"$ref":"#/components/schemas/RunId"}}],"responses":{"202":{"description":"Abort requested","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbortAccepted"}}}},"400":{"description":"A malformed external id in the path","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/chats/external/{external_id}/history":{"get":{"tags":["customer-api","Chats"],"summary":"Read chat history by external id","description":"The same as GET /api/v1/chats/{chat_id}/history, for the chat holding this external id.","operationId":"getChatHistoryByExternalId","parameters":[{"name":"external_id","in":"path","description":"Your own identifier for the chat","required":true,"schema":{"$ref":"#/components/schemas/ExternalChatId"}},{"name":"before_ordinal","in":"query","description":"Page **backwards** from here: the parts immediately older than this\nordinal. What a reader scrolling up sends, using the `first_ordinal` of\nthe page they already have.","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"after_ordinal","in":"query","description":"Page **forwards** from here: the parts immediately newer than this\nordinal. What a UI already open sends to pick up what has arrived since,\nusing `last_ordinal`.\n\nAn **ordinal**, not a part id, because ordinals are the ledger's only\ntotal order and a client paging already holds the one it saw last. They\nare never renumbered, so a cursor stays valid; deletes leave gaps, so a\ncursor is not an index and must not be incremented by hand.","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"limit","in":"query","description":"1–100, or 1–20 with `include=full`. Out-of-range values are clamped, not\nrejected.","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"include","in":"query","description":"How much of an attachment travels: `stubs` (the default), `none`, or\n`full`.","required":false,"schema":{"type":"string","description":"The `include` parameter's vocabulary.\n\nNamed for what the client gets rather than for what we do — `stubs` is the\ndescriptor, `full` adds the bytes — because the caller is choosing the size\nof their response, not a storage strategy.","enum":["stubs","none","full"]}},{"name":"include_client_data","in":"query","description":"`true` adds each part's `client_data`, for the parts that were submitted\nwith some. Off by default, since it is a second object per such part.","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Read chat history by external id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryPageResponse"}}}},"400":{"description":"A malformed external id in the path","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/chats/external/{external_id}/import":{"post":{"tags":["customer-api","Chats"],"summary":"Import a conversation by external id","description":"Store an existing conversation as the history of the chat holding this external id, creating the chat if there is none. Only an empty chat is written to: a chat that already has history returns 200 with skipped: true and nothing is stored or charged, which makes retries and races safe without an idempotency key. The history is repaired into a valid conversation before it is stored: tool results that answer no open call are dropped, tool calls with no result are closed as abandoned, prompts in a turn are moved after its tool results, tool ids are replaced and tool names made provider-safe. Every change is listed in warnings. No model is called; the chat's first response compacts the history if it needs to. Charged per million estimated tokens stored. At most 500 parts.","operationId":"importChatByExternalId","parameters":[{"name":"external_id","in":"path","description":"Your own identifier for the chat","required":true,"schema":{"$ref":"#/components/schemas/ExternalChatId"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportChatRequest"}}},"required":true},"responses":{"200":{"description":"The chat already had history; nothing was stored","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportSkippedResponse"}}}},"201":{"description":"Imported","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportChatResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"402":{"description":"The balance does not cover the import","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"chat_busy: a turn is running on this chat; retry after Retry-After seconds. external_id_namespace_mismatch: the chat exists in another namespace.","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds to wait before retrying. Sent with chat_busy."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"413":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/chats/external/{external_id}/responses":{"post":{"tags":["customer-api","Responses"],"summary":"Submit a turn by external id","description":"The same as POST /api/v1/chats/{chat_id}/responses, for the chat holding this external id, which is created on first use. The optional chat object describes the chat to create; on an existing chat it is ignored, except that a namespace you send that differs from the chat's returns 409 external_id_namespace_mismatch; leaving namespace out skips the check. Send \"stream\": false to receive one JSON object instead of an event stream.","operationId":"createResponseByExternalId","parameters":[{"name":"external_id","in":"path","description":"Your own identifier for the chat","required":true,"schema":{"$ref":"#/components/schemas/ExternalChatId"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateResponseRequest"}}},"required":true},"responses":{"200":{"description":"The answer: an event stream by default, or one JSON object with stream: false","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/ResponseEvent"}},"application/json":{"schema":{"$ref":"#/components/schemas/ResponseBody"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"402":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"chat_busy, tool_calls_pending, idempotency_key_reused or external_id_namespace_mismatch. The first two carry Retry-After.","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds to wait before retrying. Sent with chat_busy and tool_calls_pending."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"413":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"response_timeout: with stream: false, the turn outlasted the request. It continues and is billed. With an idempotency_key, retry with it to receive the result; without one, do not resend.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/chats/external/{external_id}/runs":{"get":{"tags":["customer-api","Runs"],"summary":"List a chat's runs by external id","description":"The same as GET /api/v1/chats/{chat_id}/runs, for the chat holding this external id.","operationId":"listChatRunsByExternalId","parameters":[{"name":"external_id","in":"path","description":"Your own identifier for the chat","required":true,"schema":{"$ref":"#/components/schemas/ExternalChatId"}},{"name":"after_id","in":"query","description":"Page **older** than this run id.","required":false,"schema":{"$ref":"#/components/schemas/RunId"}},{"name":"before_id","in":"query","description":"Page **newer** than this run id.","required":false,"schema":{"$ref":"#/components/schemas/RunId"}},{"name":"limit","in":"query","description":"1–100. Out-of-range values are clamped.","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"List a chat's runs by external id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunPage"}}}},"400":{"description":"A malformed external id in the path","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/chats/{chat_id}":{"get":{"tags":["customer-api","Chats"],"summary":"Get a chat","description":"Fetch a chat owned by the authenticated organisation. Missing chats and chats owned by another organisation both return 404. Pass include=usage to add the chat's cost and token totals.","operationId":"getChat","parameters":[{"name":"chat_id","in":"path","description":"Resource identifier","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"include","in":"query","description":"`usage` adds the chat's cost and token totals.","required":false,"schema":{"type":"string","description":"The chat `include` parameter's vocabulary.","enum":["usage"]}}],"responses":{"200":{"description":"Get a chat","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatSummary"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]},"delete":{"tags":["customer-api","Chats"],"summary":"Delete a chat","description":"Delete a chat and its history. A turn in progress is aborted. The chat's content is unrecoverable once this returns, and its stored objects are removed in the background shortly after. Usage and cost records are kept for billing, and GET /api/v1/runs/{run_id} still answers for its runs. Repeating the deletion returns 404.","operationId":"deleteChat","parameters":[{"name":"chat_id","in":"path","description":"Resource identifier","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Delete a chat"},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]},"patch":{"tags":["customer-api","Chats"],"summary":"Update a chat","description":"Change a chat's title, description or user_metadata. Fields left out are unchanged. A title or description sent as null or an empty string is removed. user_metadata is merged one top-level key at a time: keys you send replace the stored ones, keys sent as null are removed, and the merged result must fit the 1 KB cap. The namespace and external id cannot be changed. Returns the updated chat.","operationId":"updateChat","parameters":[{"name":"chat_id","in":"path","description":"Resource identifier","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateChatRequest"}}},"required":true},"responses":{"200":{"description":"The updated chat","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatSummary"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"413":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/chats/{chat_id}/abort":{"post":{"tags":["customer-api","Responses"],"summary":"Abort the turn in progress","description":"Stop the chat's in-progress turn. Completed blocks and a cut-off text block are kept; a cut-off reasoning block or tool call is dropped. Returns 409 no_active_turn when nothing is running, and 409 run_not_active when run_id names a run that is not the chat's live turn.","operationId":"abortResponse","parameters":[{"name":"chat_id","in":"path","description":"Resource identifier","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"run_id","in":"query","description":"The run you mean to stop: the `run_id` from the stream's `run` event.\nOptional. When given, nothing else is stopped, so an abort that arrives\nlate cannot stop the chat's *next* turn by mistake.","required":false,"schema":{"$ref":"#/components/schemas/RunId"}}],"responses":{"202":{"description":"Abort requested","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbortAccepted"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/chats/{chat_id}/history":{"get":{"tags":["customer-api","Chats"],"summary":"Read chat history","description":"Read the newest page by default, with rows ordered oldest first. Use before_ordinal or after_ordinal, not both. Unknown query parameters return 422.","operationId":"getChatHistory","parameters":[{"name":"chat_id","in":"path","description":"Resource identifier","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"before_ordinal","in":"query","description":"Page **backwards** from here: the parts immediately older than this\nordinal. What a reader scrolling up sends, using the `first_ordinal` of\nthe page they already have.","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"after_ordinal","in":"query","description":"Page **forwards** from here: the parts immediately newer than this\nordinal. What a UI already open sends to pick up what has arrived since,\nusing `last_ordinal`.\n\nAn **ordinal**, not a part id, because ordinals are the ledger's only\ntotal order and a client paging already holds the one it saw last. They\nare never renumbered, so a cursor stays valid; deletes leave gaps, so a\ncursor is not an index and must not be incremented by hand.","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"limit","in":"query","description":"1–100, or 1–20 with `include=full`. Out-of-range values are clamped, not\nrejected.","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"include","in":"query","description":"How much of an attachment travels: `stubs` (the default), `none`, or\n`full`.","required":false,"schema":{"type":"string","description":"The `include` parameter's vocabulary.\n\nNamed for what the client gets rather than for what we do — `stubs` is the\ndescriptor, `full` adds the bytes — because the caller is choosing the size\nof their response, not a storage strategy.","enum":["stubs","none","full"]}},{"name":"include_client_data","in":"query","description":"`true` adds each part's `client_data`, for the parts that were submitted\nwith some. Off by default, since it is a second object per such part.","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Read chat history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryPageResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/chats/{chat_id}/responses":{"post":{"tags":["customer-api","Responses"],"summary":"Submit a turn and get the answer","description":"Submit a prompt or tool results. By default the answer streams as server-sent events: failures before the first byte use HTTP errors and later failures use the error event. With \"stream\": false the answer is one JSON object and every failure is an HTTP error; failures after the turn started carry details.run_id, and reusing an idempotency_key whose run finished, with the same input, returns that run's result with replayed: true. Dropping the connection does not cancel the turn. A chat already running a turn returns 409 chat_busy with Retry-After. A reused idempotency key otherwise returns 409 idempotency_key_reused with details.run_id. With wait_for_pending_tool_calls set, a submission that would close a recent unanswered tool call returns 409 tool_calls_pending with Retry-After.","operationId":"createResponse","parameters":[{"name":"chat_id","in":"path","description":"Resource identifier","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateResponseRequest"}}},"required":true},"responses":{"200":{"description":"The answer: an event stream by default, or one JSON object with stream: false","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/ResponseEvent"}},"application/json":{"schema":{"$ref":"#/components/schemas/ResponseBody"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"402":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"chat_busy: the chat is running another turn; retry after Retry-After seconds. tool_calls_pending: the submission would close tool calls inside wait_for_pending_tool_calls; answer them or retry after Retry-After seconds. idempotency_key_reused: details.run_id names the run that owns the key.","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds to wait before retrying. Sent with chat_busy and tool_calls_pending."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"413":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"response_timeout: with stream: false, the turn outlasted the request. It continues and is billed. With an idempotency_key, retry with it to receive the result; without one, do not resend.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/chats/{chat_id}/runs":{"get":{"tags":["customer-api","Runs"],"summary":"List a chat's runs","description":"List the runs on a chat newest first: customer turns and the compaction runs Twigg made on the chat's behalf, with status, model, token usage, cost and timing. The context manifest is left out; read it with GET /api/v1/runs/{run_id}. Use after_id or before_id to page; they are mutually exclusive. A deleted chat returns 404.","operationId":"listChatRuns","parameters":[{"name":"chat_id","in":"path","description":"Resource identifier","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"after_id","in":"query","description":"Page **older** than this run id.","required":false,"schema":{"$ref":"#/components/schemas/RunId"}},{"name":"before_id","in":"query","description":"Page **newer** than this run id.","required":false,"schema":{"$ref":"#/components/schemas/RunId"}},{"name":"limit","in":"query","description":"1–100. Out-of-range values are clamped.","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"List a chat's runs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunPage"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config":{"delete":{"tags":["customer-api","Configuration"],"summary":"Delete configuration under a namespace prefix","description":"Permanently delete every instruction, tool, retention and context budget version, active or not, in namespace_prefix and every namespace beneath it. Organisation-wide configuration is never touched. Chats in those namespaces keep working and resolve against what their ancestors still configure. Unlike withdrawing, this cannot be undone, and the deleted version ids return 404 afterwards, including from runs that used them. Returns how many versions were deleted; a prefix with nothing configured returns zeros.","operationId":"deleteConfiguration","parameters":[{"name":"namespace_prefix","in":"query","description":"Deletes this namespace's configuration and that of every namespace\nbeneath it, by path segment: `swarm/run-abc` covers\n`swarm/run-abc/planner-1` but not `swarm/run-abcd`.","required":true,"schema":{"$ref":"#/components/schemas/Namespace"}}],"responses":{"200":{"description":"Deleted version counts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigDeletion"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/budgets":{"get":{"tags":["customer-api","Configuration"],"summary":"List active context budgets","operationId":"listActiveBudgets","parameters":[{"name":"namespace","in":"query","required":false,"schema":{"$ref":"#/components/schemas/Namespace"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContextBudgetResponse"}}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]},"post":{"tags":["customer-api","Configuration"],"summary":"Publish context budgets","operationId":"publishBudgets","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishContextBudgetRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContextBudgetResponse"}}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/budgets/active":{"delete":{"tags":["customer-api","Configuration"],"summary":"Withdraw context budget","operationId":"withdrawBudget","parameters":[{"name":"namespace","in":"query","required":false,"schema":{"$ref":"#/components/schemas/Namespace"}},{"name":"model","in":"query","required":false,"schema":{"$ref":"#/components/schemas/ModelId"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeactivateResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/budgets/versions":{"get":{"tags":["customer-api","Configuration"],"summary":"List context budget versions","operationId":"listBudgetVersions","parameters":[{"name":"namespace","in":"query","required":false,"schema":{"$ref":"#/components/schemas/Namespace"}},{"name":"model","in":"query","required":false,"schema":{"$ref":"#/components/schemas/ModelId"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContextBudgetResponse"}}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/budgets/{id}/activate":{"post":{"tags":["customer-api","Configuration"],"summary":"restoreBudget","operationId":"restoreBudget","parameters":[{"name":"id","in":"path","required":true,"schema":{"$ref":"#/components/schemas/ContextBudgetPolicyId"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContextBudgetResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/defaults":{"get":{"tags":["customer-api","Configuration"],"summary":"Read default policies","operationId":"getConfigurationDefaults","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DefaultPoliciesResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/instructions":{"get":{"tags":["customer-api","Configuration"],"summary":"listInstructionVersions","operationId":"listInstructionVersions","parameters":[{"name":"namespace","in":"query","required":false,"schema":{"$ref":"#/components/schemas/Namespace"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConfigVersionResponse"}}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]},"post":{"tags":["customer-api","Configuration"],"summary":"Publish system instructions","operationId":"publishInstructions","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishInstructionRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigVersionResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/instructions/active":{"delete":{"tags":["customer-api","Configuration"],"summary":"withdrawInstructions","operationId":"withdrawInstructions","parameters":[{"name":"namespace","in":"query","required":false,"schema":{"$ref":"#/components/schemas/Namespace"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeactivateResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/instructions/{id}":{"get":{"tags":["customer-api","Configuration"],"summary":"Read instruction version","operationId":"getInstructions","parameters":[{"name":"id","in":"path","required":true,"schema":{"$ref":"#/components/schemas/SystemInstructionId"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstructionResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/instructions/{id}/activate":{"post":{"tags":["customer-api","Configuration"],"summary":"restoreInstructions","operationId":"restoreInstructions","parameters":[{"name":"id","in":"path","required":true,"schema":{"$ref":"#/components/schemas/SystemInstructionId"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigVersionResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/namespaces":{"get":{"tags":["customer-api","Configuration"],"summary":"List namespaces used by chats or configuration","operationId":"listConfigurationNamespaces","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Namespace"}}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/resolved":{"get":{"tags":["customer-api","Configuration"],"summary":"Resolve effective configuration","operationId":"resolveConfiguration","parameters":[{"name":"namespace","in":"query","required":false,"schema":{"$ref":"#/components/schemas/Namespace"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolvedConfig"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/resolved-budget":{"get":{"tags":["customer-api","Configuration"],"summary":"Resolve effective context budget","operationId":"resolveContextBudget","parameters":[{"name":"namespace","in":"query","required":false,"schema":{"$ref":"#/components/schemas/Namespace"}},{"name":"model","in":"query","required":false,"schema":{"$ref":"#/components/schemas/ModelId"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolvedBudget"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/retention":{"get":{"tags":["customer-api","Configuration"],"summary":"listRetentionVersions","operationId":"listRetentionVersions","parameters":[{"name":"namespace","in":"query","required":false,"schema":{"$ref":"#/components/schemas/Namespace"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RetentionPolicyResponse"}}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]},"post":{"tags":["customer-api","Configuration"],"summary":"Publish retention policy","operationId":"publishRetention","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishRetentionPolicyRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionPolicyResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/retention/active":{"delete":{"tags":["customer-api","Configuration"],"summary":"withdrawRetention","operationId":"withdrawRetention","parameters":[{"name":"namespace","in":"query","required":false,"schema":{"$ref":"#/components/schemas/Namespace"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeactivateResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/retention/{id}/activate":{"post":{"tags":["customer-api","Configuration"],"summary":"restoreRetention","operationId":"restoreRetention","parameters":[{"name":"id","in":"path","required":true,"schema":{"$ref":"#/components/schemas/RetentionPolicyId"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionPolicyResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/tools":{"get":{"tags":["customer-api","Configuration"],"summary":"listToolVersions","operationId":"listToolVersions","parameters":[{"name":"namespace","in":"query","required":false,"schema":{"$ref":"#/components/schemas/Namespace"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConfigVersionResponse"}}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]},"post":{"tags":["customer-api","Configuration"],"summary":"Publish saved tools","operationId":"publishTools","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishToolsRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigVersionResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/tools/active":{"delete":{"tags":["customer-api","Configuration"],"summary":"withdrawTools","operationId":"withdrawTools","parameters":[{"name":"namespace","in":"query","required":false,"schema":{"$ref":"#/components/schemas/Namespace"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeactivateResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/tools/{id}":{"get":{"tags":["customer-api","Configuration"],"summary":"Read tool version","operationId":"getTools","parameters":[{"name":"id","in":"path","required":true,"schema":{"$ref":"#/components/schemas/ToolSchemaId"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolSchemaResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/config/tools/{id}/activate":{"post":{"tags":["customer-api","Configuration"],"summary":"restoreTools","operationId":"restoreTools","parameters":[{"name":"id","in":"path","required":true,"schema":{"$ref":"#/components/schemas/ToolSchemaId"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigVersionResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/models":{"get":{"tags":["customer-api","Catalogue"],"summary":"List available models","description":"Returns active models available for new requests, with the caller's prices.","operationId":"listModels","responses":{"200":{"description":"List available models","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CatalogueModel"}}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/namespaces":{"get":{"tags":["customer-api","Catalogue"],"summary":"List namespaces in use","description":"Unpaged, deliberately. A namespace count is bounded by how a customer scopes\nrather than by how much they use the product, and a cursor on a list nobody\nwill page is API surface with no reader.","operationId":"listNamespaces","responses":{"200":{"description":"List namespaces in use","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NamespacePage"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/runs/{run_id}":{"get":{"tags":["customer-api","Runs"],"summary":"Inspect a run","description":"`404` for a run in another organisation, exactly as for one that does not\nexist. The scoping is in the query rather than a check after it, so there is\nno timing difference and no way to probe for someone else's run id.","operationId":"getRun","parameters":[{"name":"run_id","in":"path","description":"Resource identifier","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Inspect a run","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunInspection"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/updates":{"get":{"tags":["public-info"],"summary":"List published updates","operationId":"listPublicUpdates","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PublicPlatformUpdate"}}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{}]}},"/api/v1/usage":{"get":{"tags":["customer-api","Usage"],"summary":"Query organisation or namespace usage","operationId":"queryUsage","parameters":[{"name":"range","in":"query","required":true,"schema":{"type":"string","enum":["24h","7d","30d","90d"]}},{"name":"bin","in":"query","description":"Absent means \"do not bin\" — the window's totals, or one row per group.","required":false,"schema":{"$ref":"#/components/schemas/UsageBin"}},{"name":"group_by","in":"query","description":"Absent means \"do not split\" — the organisation as a whole.","required":false,"schema":{"$ref":"#/components/schemas/UsageDimension"}},{"name":"namespace","in":"query","description":"Absent is the whole organisation. Present reports the namespace **and its\nsubtree**, which is a different question from the namespace alone and the\none a customer with per-project paths is asking.","required":false,"schema":{"$ref":"#/components/schemas/Namespace"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageReport"}}}},"401":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/version":{"get":{"tags":["Discovery"],"operationId":"get","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiVersion"}}}}},"security":[]}},"/v1/catalogue":{"get":{"tags":["public-catalogue","Catalogue"],"summary":"List public model prices","description":"No API key required. Anonymous requests use platform-default prices. A valid console session uses that organisation's markup; an invalid session is treated as anonymous.","operationId":"listCatalogue","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Catalogue"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/catalogue/models.md":{"get":{"tags":["public-catalogue","Catalogue"],"summary":"Read model prices as Markdown","description":"No API key required. Anonymous requests use platform-default prices. A valid console session uses that organisation's markup; an invalid session is treated as anonymous.","operationId":"getCatalogueMarkdown","responses":{"200":{"description":"","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/catalogue/{name}":{"get":{"tags":["public-catalogue","Catalogue"],"summary":"Get public model prices","description":"No API key required. Anonymous requests use platform-default prices. A valid console session uses that organisation's markup; an invalid session is treated as anonymous.","operationId":"getCatalogueModel","parameters":[{"name":"name","in":"path","description":"Public model name; may include slashes.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogueModelResponse"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}}},"components":{"schemas":{"AbortAccepted":{"type":"object","description":"An abort that was accepted.","required":["run_id","chat_id","status"],"properties":{"chat_id":{"$ref":"#/components/schemas/ChatId"},"run_id":{"$ref":"#/components/schemas/RunId"},"status":{"type":"string","description":"Always `aborting`. The turn stops on the instance running it; its\noutcome arrives as the stream's `done` event with `stop_reason:\naborted`, and on `GET /api/v1/runs/{run_id}` as status `cancelled`.\nAn abort that arrives as the turn is finishing can lose that race: the\nturn then ends normally and `done` carries its own `stop_reason`."}}},"ApiKeyId":{"type":"string","format":"uuid"},"ApiKeyUsageGroup":{"type":"object","description":"`None` covers events with no key: console-initiated work, and credits.","required":["dimension"],"properties":{"api_key_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ApiKeyId"}]},"dimension":{"type":"string","enum":["api_key"]}}},"ApiVersion":{"type":"object","required":["version","commit","api_version"],"properties":{"api_version":{"type":"string"},"commit":{"type":"string"},"version":{"type":"string"}}},"BalanceEntryType":{"type":"string","enum":["usage","compaction","import","topup","refund","adjustment","promotional_credit"]},"BilledRates":{"type":"object","description":"Per-million rates as the customer pays them.","required":["input","output","currency"],"properties":{"cache_read":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/RatePerMillion","description":"Absent when the provider does not meter it."}]},"cache_write":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/RatePerMillion"}]},"currency":{"type":"string"},"input":{"$ref":"#/components/schemas/RatePerMillion"},"output":{"$ref":"#/components/schemas/RatePerMillion"}}},"BilledTier":{"type":"object","description":"One pricing condition, in the customer's terms. Rates here are billed too.","required":["id","mode","metric","min"],"properties":{"cache_read":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/RatePerMillion"}]},"cache_write":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/RatePerMillion"}]},"id":{"type":"string"},"input":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/RatePerMillion"}]},"max":{"type":["integer","null"],"format":"int64","minimum":0},"metric":{"type":"string"},"min":{"type":"integer","format":"int64","minimum":0},"mode":{"$ref":"#/components/schemas/TierMode"},"output":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/RatePerMillion"}]}}},"BlockStart":{"oneOf":[{"$ref":"#/components/schemas/TextBlockStart"},{"$ref":"#/components/schemas/ReasoningBlockStart"},{"$ref":"#/components/schemas/RefusalBlockStart"},{"$ref":"#/components/schemas/ToolCallBlockStart"}],"discriminator":{"propertyName":"kind","mapping":{"reasoning":"#/components/schemas/ReasoningBlockStart","refusal":"#/components/schemas/RefusalBlockStart","text":"#/components/schemas/TextBlockStart","tool_call":"#/components/schemas/ToolCallBlockStart"}}},"BlockStartEvent":{"type":"object","required":["data","event"],"properties":{"data":{"$ref":"#/components/schemas/BlockStart"},"event":{"type":"string","enum":["block_start"]}}},"BlockStopEvent":{"type":"object","required":["data","event"],"properties":{"data":{"$ref":"#/components/schemas/BlockStopEventData"},"event":{"type":"string","enum":["block_stop"]}}},"BlockStopEventData":{"type":"object"},"BudgetFraction":{"type":"number","format":"float"},"BudgetSource":{"oneOf":[{"$ref":"#/components/schemas/PlatformDefaultBudgetSource"},{"$ref":"#/components/schemas/PolicyBudgetSource"}],"description":"The configuration scope and model tag that supplied the resolved context budget.","discriminator":{"propertyName":"kind","mapping":{"platform_default":"#/components/schemas/PlatformDefaultBudgetSource","policy":"#/components/schemas/PolicyBudgetSource"}}},"Catalogue":{"type":"object","description":"The whole catalogue plus the margin its prices include.","required":["models","routers","markup_percent","organisation_specific"],"properties":{"markup_percent":{"$ref":"#/components/schemas/MarkupPercent","description":"The platform-default markup the listed prices already include. Zero\nmeans the prices are provider cost."},"models":{"type":"array","items":{"$ref":"#/components/schemas/CatalogueModel"}},"organisation_specific":{"type":"boolean","description":"Present when a signed-in caller's organisation has its own rate; the\nprices then reflect that rate rather than the default."},"routers":{"type":"array","items":{"$ref":"#/components/schemas/CatalogueRouter"},"description":"Routers that choose among `models` per turn."}}},"CatalogueModel":{"type":"object","description":"One catalogue entry, in full. The list and the detail share it: a detail\npage is not a different fact, only a bigger frame around the same one.","required":["id","name","display_name","provider","provider_label","model_family","context_window","max_output_tokens","supports_reasoning","supports_tools","media","thinking","rates","tiers"],"properties":{"avg_time_to_first_token_ms":{"type":["number","null"],"format":"double","description":"Mean milliseconds from provider request to first nonempty output delta,\nover successful requests completed in the last 24 hours. Includes retry waits.\nNull when no timing samples exist. Refreshed every 15 minutes."},"context_window":{"type":"integer","format":"int32"},"display_name":{"type":"string"},"icon_url":{"type":["string","null"]},"id":{"$ref":"#/components/schemas/ModelId"},"max_output_tokens":{"type":"integer","format":"int32"},"max_reasoning_effort":{"type":["string","null"]},"max_tool_definitions":{"type":["integer","null"],"format":"int32"},"media":{"$ref":"#/components/schemas/MediaCapabilities"},"model_family":{"type":"string"},"name":{"type":"string","description":"The identifier to send as `model` on a run."},"provider":{"$ref":"#/components/schemas/Provider"},"provider_label":{"type":"string"},"rates":{"$ref":"#/components/schemas/BilledRates"},"supports_reasoning":{"type":"boolean"},"supports_tools":{"type":"boolean"},"thinking":{"type":"string"},"tiers":{"type":"array","items":{"$ref":"#/components/schemas/BilledTier"}},"uptime":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Uptime","description":"Observed provider request success rate over the past 24 hours, after retries,\nas a fraction from 0 to 1. Refreshed every 15 minutes. Null means no\neligible completed requests. Local validation failures, interrupted runs\nand unclassified historical failures are excluded; this is not time-based uptime."}]}}},"CatalogueModelResponse":{"allOf":[{"$ref":"#/components/schemas/CatalogueModel"},{"type":"object","required":["markup_percent"],"properties":{"markup_percent":{"$ref":"#/components/schemas/MarkupPercent"}}}]},"CatalogueRouter":{"type":"object","description":"A model router: named as `model` like any model, it chooses one of its\ncandidates for each turn. It has no prices of its own; a turn is billed at\nthe chosen model's, which the run reports.","required":["id","name","display_name","vendor","vendor_label","description","candidates","fallback_model"],"properties":{"candidates":{"type":"array","items":{"type":"string"},"description":"The `name`s of the models it may choose. Each is in `models`."},"description":{"type":"string","description":"What it does, including what it sends to the vendor."},"display_name":{"type":"string"},"fallback_model":{"type":"string","description":"The `name` of the model it serves when the vendor cannot choose."},"id":{"$ref":"#/components/schemas/RouterId"},"name":{"type":"string","description":"The identifier to send as `model` on a run."},"vendor":{"$ref":"#/components/schemas/RouterVendor"},"vendor_label":{"type":"string"}}},"ChatCreated":{"type":"object","description":"The new chat, including its immutable namespace, labels, metadata and creation time.","required":["id","namespace","title","description","external_id","user_metadata","created_at"],"properties":{"created_at":{"type":"string","format":"date-time"},"description":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChatDescription"}]},"external_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ExternalChatId"}]},"id":{"$ref":"#/components/schemas/ChatId"},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace"}]},"title":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChatTitle"}]},"user_metadata":{"$ref":"#/components/schemas/UserMetadata","description":"Echoed from the request, like the labels above — but for a different\nreason. This one *is* readable from the row; it is echoed so the\nresponse reflects what the customer sent rather than what `jsonb`\nnormalisation made of it, and so all three optional fields behave the\nsame way here."}}},"ChatDescription":{"type":"string","maxLength":200,"minLength":1},"ChatId":{"type":"string","format":"uuid"},"ChatPage":{"type":"object","description":"One page of chats.","required":["data","first_id","last_id","has_more"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ChatSummary"},"description":"Newest first, whichever direction was paged.\n\nNamed `data` rather than `chats` so one pagination helper works across\nevery list endpoint we add — the same reason the upstream APIs do it."},"first_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChatId","description":"Id of the first item in `data`. Pass as `before_id` to page backwards.\n`null` when the page is empty."}]},"has_more":{"type":"boolean","description":"Whether more chats exist **in the direction being paged**."},"last_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChatId","description":"Id of the last item in `data`. Pass as `after_id` for the next page."}]}}},"ChatPartId":{"type":"string","format":"uuid"},"ChatSummary":{"type":"object","description":"One chat in a listing.\n\nEverything optional here is optional in the customer's data, not in our\nresponse: `null` means they did not set it, and the field is always present\nso a client never has to distinguish \"absent\" from \"unset\".","required":["id","namespace","title","description","external_id","user_metadata","length","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time"},"description":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChatDescription"}]},"external_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ExternalChatId","description":"The customer's own id for the chat, when it was opened with one."}]},"id":{"$ref":"#/components/schemas/ChatId"},"length":{"type":"integer","format":"int64","description":"How many parts the chat's ledger holds.\n\nA count of rows, not of tokens, characters or messages — one assistant\nturn can be several parts (reasoning, then text, then a tool call), so\nthis is larger than the number of exchanges a customer would count by\neye. It is meant as an \"is there anything in here, and roughly how\nmuch\" signal, not as an addressing scheme: ordinals are never\nrenumbered and deletes leave gaps, so the last part's ordinal is not\n`length - 1`."},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace"}]},"title":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChatTitle"}]},"updated_at":{"type":"string","format":"date-time"},"usage":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChatUsage","description":"Cost and token totals. Present only when the request asked for them with\n`include=usage`."}]},"user_metadata":{"$ref":"#/components/schemas/UserMetadata"}}},"ChatTitle":{"type":"string","maxLength":50,"minLength":1},"ChatUsage":{"type":"object","description":"What a chat has used so far, summed over its runs.","required":["cost","input_tokens","output_tokens","cache_read_tokens","cache_write_tokens","reasoning_tokens","runs","unsettled_runs"],"properties":{"cache_read_tokens":{"type":"integer","format":"int64"},"cache_write_tokens":{"type":"integer","format":"int64"},"cost":{"type":"string","description":"What the chat has been charged, in the platform currency: settled runs\nonly. Compaction runs are included, since they are billed."},"input_tokens":{"type":"integer","format":"int64"},"output_tokens":{"type":"integer","format":"int64"},"reasoning_tokens":{"type":"integer","format":"int64","description":"The thinking share of `output_tokens`, not an addition to it."},"runs":{"type":"integer","format":"int64","description":"Every run on the chat, failed and compaction runs included."},"unsettled_runs":{"type":"integer","format":"int64","description":"Runs that may still add to `cost`: in flight, or finished and awaiting\nsettlement."}}},"ChatsDeleted":{"type":"object","description":"What [`delete_subtree`] deleted.","required":["deleted"],"properties":{"deleted":{"type":"integer","format":"int64","description":"Live chats deleted by this call. Chats already deleted are not counted.","minimum":0}}},"ChosenRoute":{"type":"object","description":"The vendor chose it for this turn.","required":["kind"],"properties":{"kind":{"type":"string","enum":["chosen"]}}},"ClientData":{"type":"object","description":"Your own JSON for this part, at most 65536 bytes when serialized compactly. null is the same as leaving it out. Stored encrypted beside the part, never sent to a model, and returned by the history endpoint with include_client_data=true."},"CompactingEvent":{"type":"object","description":"Compaction work the request is waiting for.","required":["data","event"],"properties":{"data":{"$ref":"#/components/schemas/CompactingEventData"},"event":{"type":"string","enum":["compacting"]}}},"CompactingEventData":{"type":"object","description":"Compaction work the request is waiting for.","required":["blocks","in_progress_elsewhere"],"properties":{"blocks":{"type":"integer","minimum":0},"in_progress_elsewhere":{"type":"integer","minimum":0}}},"Compaction":{"type":"object","required":["blocks_generated","blocks_reused","in_progress_elsewhere"],"properties":{"blocks_generated":{"type":"integer","minimum":0},"blocks_reused":{"type":"integer","minimum":0},"in_progress_elsewhere":{"type":"integer","minimum":0}}},"ConfigDeletion":{"type":"object","description":"Row counts per config table. Every version is counted, active or not.","required":["instructions","tools","retention_policies","context_budgets"],"properties":{"context_budgets":{"type":"integer","format":"int64","minimum":0},"instructions":{"type":"integer","format":"int64","minimum":0},"retention_policies":{"type":"integer","format":"int64","minimum":0},"tools":{"type":"integer","format":"int64","minimum":0}}},"ConfigMode":{"type":"string","enum":["append","replace"]},"ConfigVersionResponse":{"type":"object","description":"One published version, without its payload. The body of an instruction and\nthe definitions of a bundle are fetched per version, not listed — a history\nendpoint that returned every body would fetch and decrypt a blob per row.","required":["id","version","estimated_tokens","is_active","created_at"],"properties":{"created_at":{"type":"string","format":"date-time"},"estimated_tokens":{"$ref":"#/components/schemas/TokenEstimate"},"id":{"type":"string"},"is_active":{"type":"boolean"},"mode":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ConfigMode","description":"How this version combines with the org-global one — `None` for the two\nsurfaces that do not combine at all (retention policies and context\nbudgets), where a mode would be a field the customer could set and\nnothing would read."}]},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace"}]},"version":{"type":"integer","format":"int32"}}},"ConfigWarning":{"oneOf":[{"$ref":"#/components/schemas/ToolShadowedWarning"},{"$ref":"#/components/schemas/GlobalInstructionReplacedWarning"},{"$ref":"#/components/schemas/GlobalToolsReplacedWarning"},{"$ref":"#/components/schemas/RetentionPolicyOverriddenWarning"},{"$ref":"#/components/schemas/ContextBudgetResolvedAtWarning"},{"$ref":"#/components/schemas/HistoryDroppedWarning"},{"$ref":"#/components/schemas/ProviderKeyPausedWarning"},{"$ref":"#/components/schemas/ProviderKeyFellThroughWarning"},{"$ref":"#/components/schemas/ModelRoutedWarning"}],"description":"Something legal but worth saying out loud.","discriminator":{"propertyName":"code","mapping":{"context_budget_resolved_at":"#/components/schemas/ContextBudgetResolvedAtWarning","global_instruction_replaced":"#/components/schemas/GlobalInstructionReplacedWarning","global_tools_replaced":"#/components/schemas/GlobalToolsReplacedWarning","history_dropped":"#/components/schemas/HistoryDroppedWarning","model_routed":"#/components/schemas/ModelRoutedWarning","provider_key_fell_through":"#/components/schemas/ProviderKeyFellThroughWarning","provider_key_paused":"#/components/schemas/ProviderKeyPausedWarning","retention_policy_overridden":"#/components/schemas/RetentionPolicyOverriddenWarning","tool_shadowed":"#/components/schemas/ToolShadowedWarning"}}},"ConfigWarningsEvent":{"type":"object","description":"Configuration warnings; emitted second, and may repeat after compaction.","required":["data","event"],"properties":{"data":{"$ref":"#/components/schemas/ConfigWarningsEventData"},"event":{"type":"string","enum":["config_warnings"]}}},"ConfigWarningsEventData":{"type":"object","description":"Configuration warnings; emitted second, and may repeat after compaction.","required":["warnings"],"properties":{"warnings":{"type":"array","items":{"$ref":"#/components/schemas/Warning_ConfigWarning"}}}},"ContextBudget":{"type":"object","required":["version","headroom"],"properties":{"eager_compaction":{"$ref":"#/components/schemas/EagerCompaction"},"headroom":{"$ref":"#/components/schemas/BudgetFraction"},"history_mode":{"$ref":"#/components/schemas/HistoryMode"},"max_history_tokens":{"type":["integer","null"],"format":"int32","minimum":32000},"version":{"type":"integer","format":"int32","maximum":3,"minimum":3}},"additionalProperties":false},"ContextBudgetPolicyId":{"type":"string","format":"uuid"},"ContextBudgetResolvedAtWarning":{"type":"object","description":"The budget in force did not come from the plainest place: either an\nancestor level supplied it, or a model tag at the winning level displaced\nthat level's untagged policy — or both.\n\nTwo facts, one warning, because either alone misleads. \"The budget came\nfrom `acme`\" and \"the budget came from `acme`, tagged to this model\" send\nan admin to different rows, and the second is the only one that explains\nwhy a sibling model in the same namespace behaves differently.","required":["code"],"properties":{"code":{"type":"string","enum":["context_budget_resolved_at"]},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace","description":"The level that supplied it. `None` is the org-global scope."}]},"tagged_model":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ModelId","description":"`Some` when that level's tag for this model beat its untagged policy."}]}}},"ContextBudgetResponse":{"allOf":[{"$ref":"#/components/schemas/ConfigVersionResponse"},{"type":"object","required":["budget"],"properties":{"budget":{"$ref":"#/components/schemas/ContextBudget"},"model_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ModelId","description":"`None` is the scope default, not an untagged leftover."}]}}}],"description":"One context-budget version with its document and the model it is tagged to."},"CreateChatRequest":{"type":"object","description":"Body for [`create`]. Every field is optional — the minimum viable request is\n`{}`, which opens a chat in the org's default scope with no labels.\n\nThe org is deliberately absent: it comes off the authenticated key, so a\ncaller cannot open a chat anywhere but their own organisation.","properties":{"description":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChatDescription"}]},"external_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ExternalChatId","description":"Your own identifier for the chat, such as a phone number or another\nsystem's chat id. Unique within the organisation and case-sensitive.\nOnce set, the chat can be addressed at `/api/v1/chats/external/{external_id}`.\n\nNot coerced from `\"\"`, like `namespace`: it is an address, and a client\nwhose interpolation produced an empty one has a bug a 422 should show.\nStored in the database as a keyed hash plus a sealed copy. It does\nappear in request logs, because it travels in URL paths; see the\nexternal id schema."}]},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace","description":"The scope this chat's configuration resolves against, and the prefix it\nwill be listed under. Immutable once set.\n\nNote this field does **not** coerce an empty string to \"no namespace\",\nwhere `title` and `description` below do. A namespace is load-bearing —\nit decides which system instructions and tools every future run on this\nchat receives — so a client whose interpolation produced `\"\"` should get\na 422 rather than a chat silently pinned to the org-global scope. The\nlabels are decorative, and an untouched form field is not worth a\nrejection."}]},"title":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChatTitle"}]},"user_metadata":{"$ref":"#/components/schemas/UserMetadata","description":"Arbitrary customer JSON, capped at a kilobyte. Twigg never reads it —\nit is somewhere to hang a ticket reference or a UI flag so the customer\ndoes not have to keep a parallel table keyed by our ids.\n\nAbsent means an empty object, never `null`, so \"no tags\" is one stored\nvalue rather than two."}},"additionalProperties":false},"CreateResponseRequest":{"type":"object","description":"Submit a turn or retry the latest failed run. The answer streams as server-sent events by default; send \"stream\": false to receive one JSON object instead.","required":["model","input"],"properties":{"chat":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/OpenChatRequest","description":"Only on `/api/v1/chats/external/{external_id}/responses`: how to create\nthe chat if no chat holds that external id yet. Omit it to create one\nwith no namespace or labels. On an existing chat it is ignored, except\nthat a stated `namespace` that differs is refused with 409\n`external_id_namespace_mismatch`."}]},"idempotency_key":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/IdempotencyKey","description":"Prevents a second run for the same key. Org-scoped and honoured for 24 hours.\nLetters, digits and `-._~` only. A key belongs to the input it was first\nsent with; the same key with different input is always refused.\nReusing a key returns HTTP 409 `idempotency_key_reused` with the original\nrun in `details.run_id`; it does not replay the SSE stream. After a dropped\nconnection, inspect that run with GET /api/v1/runs/{run_id} and read chat\nhistory for persisted output. Do not generate a new key merely to retry an\nuncertain submission."}]},"input":{"type":"array","items":{"$ref":"#/components/schemas/SubmittedPart"},"maxItems":128,"minItems":0},"max_tokens":{"type":["integer","null"],"format":"int32","description":"Output ceiling. Only ever **lowered** — by the model's own ceiling, and\nby what the balance can pay for.","minimum":1},"model":{"type":"string","description":"The catalogue `name`, as `GET /api/v1/models` lists it — **not** the\nstring the provider spells it with.\n\nThe two are separate columns precisely so this one can stay stable: the\nwire name carries snapshot dates that vendors move under us, and a\ncustomer who pinned one would break the day an alias was re-pointed.\n\nOnly an **active** model resolves; a withdrawn one would open a turn\nnothing can continue."},"reasoning_effort":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ReasoningEffort","description":"How hard the model should think, where it can. Coerced with a warning\nrather than rejected when the model cannot honour it."}]},"retry_of":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/RunId","description":"Retry the latest failed customer run on this chat without appending input.\nSend input: [] and a new idempotency key. Supply the model, any\nrequest-level tools and any system prompt again; the retry uses the\ncurrent configuration."}]},"stream":{"type":"boolean","description":"`true` (the default) streams the answer as server-sent events. `false`\nwaits for the turn to finish and returns one JSON object: the ordered\ncontent, the text concatenated, the pending tool calls with their\narguments, usage and cost. Errors are then HTTP statuses throughout,\nincluding failures after the turn started, which carry `details.run_id`.\nWith `false`, reusing an `idempotency_key` whose run finished, with the\nsame `input`, returns that run's result again, with `replayed: true`,\ninstead of a 409. Send a key with every non-streaming request: a turn\nthat outlasts the request returns `504 response_timeout`, and only a key\nmakes retrying it safe."},"system":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SystemPrompt","description":"A system prompt for this request only.\n\nAppended after the instructions configured for the chat's namespace and\nthe organisation, never in place of them, so configured instructions\nstill apply. It is not stored in the chat's history, so send it on every\nrequest it should apply to, retries included. It is counted against the\ncontext budget like the configured instructions. An empty string is\ntreated as absent."}]},"tools":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ToolDefinition"},"description":"Tools for this request alone, in the same shape a published bundle uses.\n\nThe **nearest** level there is, so one of these shadows a namespace or\norg-global tool of the same name. They are charged against the context\nbudget like any other tool, because the provider charges for them."},"user_metadata":{"$ref":"#/components/schemas/UserMetadata","description":"Arbitrary customer JSON, attached to every part this turn writes."},"wait_for_pending_tool_calls":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PendingCallWindow","description":"Protect unanswered tool calls younger than this many seconds (1 to 600).\n\nBy default, a submission that does not answer the chat's open tool calls\ncloses them, recording each as abandoned. With this set, a submission\nthat would close a call younger than the window is refused with 409\n`tool_calls_pending` and a `Retry-After` header instead, and nothing is\nwritten. Use it when tools run elsewhere, such as in an automation\nworkflow, and a second user message can arrive while a tool is running."}]}},"additionalProperties":false},"DeactivateResponse":{"type":"object","description":"Whether anything was actually withdrawn. The call is idempotent, so `false`\nmeans \"there was no override\", not a failure.","required":["was_active"],"properties":{"was_active":{"type":"boolean"}}},"DefaultPoliciesResponse":{"type":"object","description":"The policies in force for an org that has published nothing.\n\nBoth are the platform documents themselves, not a copy: the console seeds its\neditors from this so the form a customer first sees is the policy actually\nbeing applied to their chats. Editing the shipped documents moves both at\nonce, which is the point — a hard-coded copy in the client is a second\nstatement of the same fact, and the two only ever agree until someone edits\none of them.","required":["retention","budget"],"properties":{"budget":{"$ref":"#/components/schemas/ContextBudget"},"retention":{"$ref":"#/components/schemas/RetentionRules"}}},"Delta":{"oneOf":[{"$ref":"#/components/schemas/TextDelta"},{"$ref":"#/components/schemas/ReasoningDelta"},{"$ref":"#/components/schemas/ToolInputDelta"},{"$ref":"#/components/schemas/RefusalDelta"}],"discriminator":{"propertyName":"kind","mapping":{"reasoning":"#/components/schemas/ReasoningDelta","refusal":"#/components/schemas/RefusalDelta","text":"#/components/schemas/TextDelta","tool_input":"#/components/schemas/ToolInputDelta"}}},"DeltaEvent":{"type":"object","required":["data","event"],"properties":{"data":{"$ref":"#/components/schemas/Delta"},"event":{"type":"string","enum":["delta"]}}},"Discovery":{"type":"object","required":["service","versions","openapi","docs","llms_txt"],"properties":{"docs":{"type":"string"},"llms_txt":{"type":"string"},"openapi":{"type":"string"},"service":{"type":"string"},"versions":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}}}},"DoneEvent":{"type":"object","description":"Terminal success. Null cost means settlement is pending; inspect the run later.","required":["data","event"],"properties":{"data":{"$ref":"#/components/schemas/DoneEventData"},"event":{"type":"string","enum":["done"]}}},"DoneEventData":{"type":"object","description":"Terminal success. Null cost means settlement is pending; inspect the run later.","required":["cost","cost_currency","stop_reason","usage","server_tools","model_served","provider_response_id","pending_tool_calls","compaction"],"properties":{"compaction":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Compaction"}]},"cost":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Money"}]},"cost_currency":{"type":"string"},"model_served":{"type":["string","null"],"description":"The model identifier reported by the upstream provider, when available.\nThis may differ from the catalogue name used in the request (for example,\ngpt-5-6-luna can return gpt-5.6-luna). Do not use this as a catalogue lookup key."},"pending_tool_calls":{"type":"array","items":{"$ref":"#/components/schemas/PendingCall"}},"provider_response_id":{"type":["string","null"]},"server_tools":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ServerToolUsage"}]},"stop_reason":{"$ref":"#/components/schemas/StopReason"},"usage":{"$ref":"#/components/schemas/Usage"}}},"EagerCompaction":{"oneOf":[{"$ref":"#/components/schemas/EagerCompactionOff"},{"$ref":"#/components/schemas/EagerCompactionAtFill"}],"discriminator":{"propertyName":"mode","mapping":{"at_fill":"#/components/schemas/EagerCompactionAtFill","off":"#/components/schemas/EagerCompactionOff"}}},"EagerCompactionAtFill":{"type":"object","required":["at","mode"],"properties":{"at":{"$ref":"#/components/schemas/BudgetFraction"},"mode":{"type":"string","enum":["at_fill"]}}},"EagerCompactionOff":{"type":"object","required":["mode"],"properties":{"mode":{"type":"string","enum":["off"]}}},"EntryTypeUsageGroup":{"type":"object","required":["entry_type","dimension"],"properties":{"dimension":{"type":"string","enum":["entry_type"]},"entry_type":{"$ref":"#/components/schemas/BalanceEntryType"}}},"ErrorBody":{"type":"object","description":"The customer-visible error payload, shared by HTTP errors and SSE failures.","required":["code","message"],"properties":{"code":{"type":"string"},"details":{},"hint":{"type":["string","null"]},"message":{"type":"string"}}},"ErrorEnvelope":{"type":"object","required":["error"],"properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}}},"ErrorEvent":{"type":"object","description":"Terminal failure after the stream has opened.","required":["data","event"],"properties":{"data":{"$ref":"#/components/schemas/ErrorBody","description":"Terminal failure after the stream has opened."},"event":{"type":"string","enum":["error"]}}},"ExternalChatId":{"type":"string","description":"Your own identifier for the chat, such as a phone number or a chat id from another system. Unique within your organisation, case-sensitive, printable ASCII without spaces, and without `%`, `/`, `\\`, `?`, `#` or a leading `.`, which change what a URL means. Percent-encode it in a URL path (`+` as `%2B`). It travels in URL paths, so it appears in request logs: if it identifies a person and that matters to you, send a hash or another opaque value instead of the raw identifier.","maxLength":255,"minLength":1,"pattern":"^[!\"$&--0-9:->@-\\[\\]-~][!\"$&-.0-9:->@-\\[\\]-~]*$"},"FallbackRoute":{"type":"object","description":"The router's fallback model, because the vendor's choice was unusable.","required":["reason","kind"],"properties":{"kind":{"type":"string","enum":["fallback"]},"reason":{"$ref":"#/components/schemas/RouterFallbackReason"}}},"ForeignArtifactsStrippedWarning":{"type":"object","description":"Replay artifacts the target cannot accept were stripped: ones authored by\na different model family, or Gemini signatures minted on the other Google\nendpoint (Vertex and the Gemini API reject each other's). A signature\nfrom elsewhere is meaningless, or a hard rejection, to the target.\nExpected whenever a chat hot-swaps providers, or a Gemini chat moves\nbetween Twigg's key and the customer's own, and reported so a customer\ncomparing two runs of the same chat can see why the second one lost its\nreasoning continuity.","required":["count","code"],"properties":{"code":{"type":"string","enum":["foreign_artifacts_stripped"]},"count":{"type":"integer","minimum":0}}},"GlobalInstructionReplacedWarning":{"type":"object","description":"The namespace's instruction is in `replace` mode, so the org-global\ninstruction is not being sent at all.","required":["namespace","code"],"properties":{"code":{"type":"string","enum":["global_instruction_replaced"]},"namespace":{"$ref":"#/components/schemas/Namespace"}}},"GlobalToolsReplacedWarning":{"type":"object","description":"The namespace's tool bundle is in `replace` mode, so the global bundle\nis not being sent at all — including tools the customer may assume are\nalways present.","required":["namespace","dropped","code"],"properties":{"code":{"type":"string","enum":["global_tools_replaced"]},"dropped":{"type":"integer","minimum":0},"namespace":{"$ref":"#/components/schemas/Namespace"}}},"HistoryBody":{"oneOf":[{"$ref":"#/components/schemas/HistoryPrompt"},{"$ref":"#/components/schemas/HistoryToolResult"},{"$ref":"#/components/schemas/HistoryMessage"},{"$ref":"#/components/schemas/HistoryReasoning"},{"$ref":"#/components/schemas/HistoryToolCall"}],"description":"History content: a user prompt, tool result, assistant message, reasoning or tool call.","discriminator":{"propertyName":"type","mapping":{"message":"#/components/schemas/HistoryMessage","prompt":"#/components/schemas/HistoryPrompt","reasoning":"#/components/schemas/HistoryReasoning","tool_call":"#/components/schemas/HistoryToolCall","tool_result":"#/components/schemas/HistoryToolResult"}}},"HistoryDroppedWarning":{"type":"object","description":"Oldest ledger parts were omitted because no complete context fitted.","required":["dropped","start_ordinal","end_ordinal","code"],"properties":{"code":{"type":"string","enum":["history_dropped"]},"dropped":{"type":"integer","format":"int64"},"end_ordinal":{"type":"integer","format":"int64"},"start_ordinal":{"type":"integer","format":"int64"}}},"HistoryMedia":{"type":"object","description":"An attachment, as a customer reads it back.","required":["media_id","mime","byte_len"],"properties":{"byte_len":{"type":"integer","format":"int64","minimum":0},"data_base64":{"type":["string","null"],"description":"Standard base64, present only under `include=full`."},"filename":{"type":["string","null"]},"height":{"type":["integer","null"],"format":"int32","minimum":0},"media_id":{"$ref":"#/components/schemas/MediaId"},"mime":{"type":"string"},"page_count":{"type":["integer","null"],"format":"int32","minimum":0},"width":{"type":["integer","null"],"format":"int32","minimum":0}}},"HistoryMessage":{"type":"object","description":"The model's own turn.","required":["text","type"],"properties":{"refusal":{"type":["string","null"]},"text":{"type":"string"},"type":{"type":"string","enum":["message"]}}},"HistoryMode":{"type":"string","enum":["summarize","drop_oldest"]},"HistoryPageResponse":{"type":"object","description":"One page of a chat's parts.","required":["data","first_ordinal","last_ordinal","has_more"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HistoryPart"},"description":"**Oldest first**, whichever direction was paged — a transcript is read in\nthe order it happened, so a UI appending to the bottom never reverses a\npage."},"first_ordinal":{"type":["integer","null"],"format":"int64","description":"Ordinal of the first part in `data`. Pass as `before_ordinal` to page\nfurther back. `null` when the page is empty."},"has_more":{"type":"boolean","description":"Whether more parts exist **in the direction this page was paged** —\nolder, by default and when paging back; newer, when paging forward."},"last_ordinal":{"type":["integer","null"],"format":"int64","description":"Ordinal of the last part in `data`. Pass as `after_ordinal` to pick up\nwhat arrives after it. `null` when the page is empty."}}},"HistoryPart":{"type":"object","description":"A stored chat part with its ID, position, metadata and content. Prompt and tool-result content can be reused in a new submission; assistant-authored parts cannot be submitted.","required":["id","ordinal","created_at","role","part","user_metadata"],"properties":{"client_data":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ClientData","description":"The `client_data` this part was submitted with. Present only when the\nrequest set `include_client_data=true` and the part has some.\n\nOn the envelope rather than in `part`, like `media`, so `part` stays\nexactly a submission. Copy it into the submitted part to resend it."}]},"created_at":{"type":"string","format":"date-time"},"id":{"$ref":"#/components/schemas/ChatPartId"},"media":{"type":["array","null"],"items":{"$ref":"#/components/schemas/HistoryMedia"},"description":"Attachments, when the part has any and `include` asked for them.\n\nReturned on the history envelope, separately from `part`. To resubmit an\nattachment, request `include=full` and copy its MIME type, base64 bytes and\noptional filename into the submitted prompt or tool result's `media` list.\nGenerated IDs, sizes and dimensions are read-only history metadata."},"ordinal":{"type":"integer","format":"int64"},"part":{"$ref":"#/components/schemas/HistoryBody"},"role":{"type":"string","description":"`user` or `assistant`, derived from the kind — there is no stored role.\nPresent because a UI's first decision is which side of the transcript a\npart belongs on, and deriving it from five kind names is work every\nclient would otherwise repeat."},"user_metadata":{}}},"HistoryPrompt":{"type":"object","description":"A user prompt.","required":["text","type"],"properties":{"text":{"type":"string"},"type":{"type":"string","enum":["prompt"]}}},"HistoryReasoning":{"type":"object","description":"Reasoning text exposed by the provider. Text may be empty when the\nprovider hides its reasoning. Replay signatures are not returned.","required":["text","type"],"properties":{"text":{"type":"string"},"type":{"type":"string","enum":["reasoning"]}}},"HistoryToolCall":{"type":"object","description":"A tool call the model made, for the customer to execute.","required":["tool_use_id","tool_name","arguments","type"],"properties":{"arguments":{"type":"string","description":"JSON-encoded tool arguments. Parse this string to obtain the arguments object."},"tool_name":{"type":"string"},"tool_use_id":{"$ref":"#/components/schemas/ToolUseId"},"type":{"type":"string","enum":["tool_call"]}}},"HistoryToolResult":{"type":"object","description":"A tool result. `tombstone_reason` is present only when Twigg closed a\npending call whose result never arrived; omit it when submitting results.","required":["tool_use_id","tool_name","text","is_error","trust","type"],"properties":{"is_error":{"type":"boolean"},"text":{"type":"string"},"tombstone_reason":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/TombstoneReason"}]},"tool_name":{"type":"string"},"tool_use_id":{"$ref":"#/components/schemas/ToolUseId"},"trust":{"$ref":"#/components/schemas/TrustLevel"},"type":{"type":"string","enum":["tool_result"]}}},"IdempotencyKey":{"type":"string","maxLength":128,"minLength":1},"ImportChatRequest":{"type":"object","description":"Body for [`import`].","required":["parts"],"properties":{"chat":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/OpenChatRequest","description":"Describes the chat to create when none holds this external id. Ignored\non an existing chat, except that a differing namespace is refused, as on\nthe responses route."}]},"parts":{"type":"array","items":{"$ref":"#/components/schemas/ImportPart"},"description":"The conversation, oldest first.","maxItems":500,"minItems":1}},"additionalProperties":false},"ImportChatResponse":{"type":"object","description":"201: the conversation was stored.","required":["chat_id","created_chat","imported_parts","dropped_parts","closed_tool_calls","estimated_tokens","cost","cost_currency","warnings"],"properties":{"chat_id":{"$ref":"#/components/schemas/ChatId"},"closed_tool_calls":{"type":"array","items":{"$ref":"#/components/schemas/ToolUseId"},"description":"Tool calls that had no result and were closed as abandoned, by your ids."},"cost":{"$ref":"#/components/schemas/Money","description":"The charge for this import, in USD."},"cost_currency":{"type":"string"},"created_chat":{"type":"boolean"},"dropped_parts":{"type":"integer","description":"How many were dropped; each has a warning saying why.","minimum":0},"estimated_tokens":{"type":"integer","format":"int32","description":"Estimated tokens of everything stored, which the charge is priced on.","minimum":0},"imported_parts":{"type":"integer","description":"How many of the parts you sent were stored.","minimum":0},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/ImportWarning"},"description":"Everything the import changed from what you sent."}}},"ImportMessage":{"type":"object","description":"Something the assistant said.","required":["text","type"],"properties":{"created_at":{"type":["string","null"],"format":"date-time"},"text":{"type":"string"},"type":{"type":"string","enum":["message"]}}},"ImportPart":{"oneOf":[{"$ref":"#/components/schemas/ImportPrompt"},{"$ref":"#/components/schemas/ImportMessage"},{"$ref":"#/components/schemas/ImportToolCall"},{"$ref":"#/components/schemas/ImportToolResult"}],"description":"One part of the conversation being imported.","discriminator":{"propertyName":"type","mapping":{"message":"#/components/schemas/ImportMessage","prompt":"#/components/schemas/ImportPrompt","tool_call":"#/components/schemas/ImportToolCall","tool_result":"#/components/schemas/ImportToolResult"}}},"ImportPrompt":{"type":"object","description":"Something the user said.","required":["text","type"],"properties":{"created_at":{"type":["string","null"],"format":"date-time"},"text":{"type":"string"},"type":{"type":"string","enum":["prompt"]}}},"ImportSkippedResponse":{"type":"object","description":"200: the chat already had history, so nothing was stored or charged.","required":["chat_id","skipped","existing_parts"],"properties":{"chat_id":{"$ref":"#/components/schemas/ChatId"},"existing_parts":{"type":"integer","format":"int64","description":"How many parts the chat already had."},"skipped":{"type":"boolean","description":"Always true."}}},"ImportToolCall":{"type":"object","description":"A tool the assistant called.","required":["tool_use_id","name","arguments","type"],"properties":{"arguments":{"type":"object","description":"A JSON object, or a string holding one."},"created_at":{"type":["string","null"],"format":"date-time"},"name":{"type":"string"},"tool_use_id":{"type":"string"},"type":{"type":"string","enum":["tool_call"]}}},"ImportToolResult":{"type":"object","description":"What a tool returned.","required":["tool_use_id","tool_name","type"],"properties":{"created_at":{"type":["string","null"],"format":"date-time"},"is_error":{"type":"boolean"},"text":{"type":"string"},"tool_name":{"type":"string"},"tool_use_id":{"type":"string"},"type":{"type":"string","enum":["tool_result"]}}},"ImportWarning":{"type":"object","required":["code","message"],"properties":{"code":{"$ref":"#/components/schemas/ImportWarningCode"},"message":{"type":"string"},"part_index":{"type":["integer","null"],"description":"The position in the request's `parts` this is about, when it is about\none.","minimum":0}}},"ImportWarningCode":{"type":"string","description":"Why the plan changed something the caller sent.","enum":["empty_part_dropped","unmatched_tool_result","duplicate_tool_result","empty_tool_result_filled","duplicate_tool_call","tool_call_closed","tool_name_rewritten","tool_results_moved_first","leading_assistant"]},"InstructionResponse":{"allOf":[{"$ref":"#/components/schemas/ConfigVersionResponse"},{"type":"object","required":["body"],"properties":{"body":{"type":"string"}}}],"description":"An instruction version with its body — what the editor loads."},"LlmErrorKind":{"type":"string","enum":["auth","rate_limited","overloaded","model_not_found","invalid_request","unknown"]},"MarkupPercent":{"type":"string"},"MediaCapabilities":{"type":"object","required":["configured","max_attachments_per_part","user","tool_result","assistant"],"properties":{"assistant":{"$ref":"#/components/schemas/MediaPolicy"},"configured":{"type":"boolean","description":"False means legacy adapter defaults, not verified model-level support."},"max_attachments_per_part":{"type":"integer","minimum":0},"tool_result":{"$ref":"#/components/schemas/MediaPolicy"},"user":{"$ref":"#/components/schemas/MediaPolicy"}}},"MediaCarrier":{"type":"string","enum":["user_message","assistant_message","tool_result"]},"MediaId":{"type":"string","format":"uuid"},"MediaLimitExceededWarning":{"type":"object","description":"Historical attachments exceeded the target model's byte or request-count\nlimit and were replaced with text markers. Aggregated per (MIME, carrier).","required":["mime","carrier","count","code"],"properties":{"carrier":{"$ref":"#/components/schemas/MediaCarrier"},"code":{"type":"string","enum":["media_limit_exceeded"]},"count":{"type":"integer","minimum":0},"mime":{"$ref":"#/components/schemas/MimeType"}}},"MediaPolicy":{"type":"object","required":["mime_types","max_bytes_per_attachment"],"properties":{"max_attachments_per_request":{"type":["integer","null"],"format":"int32","description":"Count across this carrier in the entire context, not per message.","minimum":0},"max_bytes_per_attachment":{"type":"integer","format":"int64","description":"Effective byte ceiling, including the platform inline attachment limit.","minimum":0},"mime_types":{"type":"array","items":{"$ref":"#/components/schemas/MimeType"}}}},"MediaRetentionRule":{"type":"object","description":"One media rule.","required":["mime","retain"],"properties":{"mime":{"$ref":"#/components/schemas/MimePattern"},"retain":{"$ref":"#/components/schemas/RecencyThreshold","description":"How recent a part must be for media of this type to be replayed."}},"additionalProperties":false},"MediaRules":{"type":"object","description":"The media section: which attachments are replayed.","properties":{"default":{"$ref":"#/components/schemas/RecencyThreshold","description":"Applied when no rule matches."},"rules":{"type":"array","items":{"$ref":"#/components/schemas/MediaRetentionRule"}}},"additionalProperties":false},"MediaUnsupportedWarning":{"type":"object","description":"Media the target model cannot receive in this position was replaced with\na text marker. Aggregated per (MIME, carrier), separately from retention.","required":["mime","carrier","count","code"],"properties":{"carrier":{"$ref":"#/components/schemas/MediaCarrier"},"code":{"type":"string","enum":["media_unsupported"]},"count":{"type":"integer","minimum":0},"mime":{"$ref":"#/components/schemas/MimeType"}}},"MimePattern":{"type":"string"},"MimeType":{"type":"string"},"ModelId":{"type":"string","format":"uuid"},"ModelRoutedWarning":{"type":"object","description":"The request named a router, and this is the model it chose. Always\npresent on a routed turn, so the customer can see what ran and why.","required":["router","model","decision","code"],"properties":{"code":{"type":"string","enum":["model_routed"]},"decision":{"$ref":"#/components/schemas/RouteDecision"},"model":{"type":"string"},"router":{"type":"string"}}},"ModelUsageGroup":{"type":"object","required":["dimension"],"properties":{"dimension":{"type":"string","enum":["model"]},"model_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ModelId","description":"Absent on a credit, which names no model."}]},"model_name":{"type":["string","null"]}}},"Money":{"type":"string","description":"A signed monetary amount in the stated currency. Negative amounts debit a balance; positive amounts credit it."},"Namespace":{"type":"string","maxLength":255,"minLength":1,"pattern":"^[a-z0-9_-]{1,64}(/[a-z0-9_-]{1,64})*$"},"NamespacePage":{"type":"object","description":"Every namespace in use, ascending.","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Namespace"},"description":"Named `data` like every other listing, so one client-side helper works\nacross the whole surface.\n\n**Chats with no namespace contribute nothing.** Absent is the org's\ndefault scope rather than a value, and returning it as one would invite a\nclient to send it back as a namespace — which is exactly the empty-string\nnamespace the create endpoint rejects."}}},"NamespaceUsageGroup":{"type":"object","description":"`None` is the org-global scope — chats created without a namespace — not\nan unknown one.","required":["dimension"],"properties":{"dimension":{"type":"string","enum":["namespace"]},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace"}]}}},"OpenChatRequest":{"type":"object","description":"How to open a chat addressed by external id, when it does not exist yet.\n\nThe fields of a create, minus the external id, which is in the path.","properties":{"description":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChatDescription"}]},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace","description":"The scope the chat's configuration resolves against, fixed when the\nchat is created. On an existing chat it is checked only when sent: a\ndifferent value (including `null` for a namespaced chat) is refused with\n409 `external_id_namespace_mismatch`, and leaving it out skips the check.\n\nTwo layers of `Option` so \"left out\" and \"`null`\" stay distinct; see\n[`NamespaceClaim`](crate::models::domain::NamespaceClaim)."}]},"title":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChatTitle"}]},"user_metadata":{"$ref":"#/components/schemas/UserMetadata"}},"additionalProperties":false},"OrganisationId":{"type":"string","format":"uuid"},"OrganisationUsageGroup":{"type":"object","description":"Usage grouped by organisation. Labels are null when unavailable.","required":["organisation_id","dimension"],"properties":{"dimension":{"type":"string","enum":["organisation"]},"name":{"type":["string","null"]},"organisation_id":{"$ref":"#/components/schemas/OrganisationId"},"slug":{"type":["string","null"]}}},"PendingCall":{"type":"object","required":["tool_use_id","tool_name"],"properties":{"tool_name":{"type":"string"},"tool_use_id":{"$ref":"#/components/schemas/ToolUseId"}}},"PendingCallWindow":{"type":"integer","maximum":600,"minimum":1},"PendingToolCallBody":{"type":"object","description":"A tool call the chat is now waiting on, with its arguments.","required":["tool_use_id","name","arguments"],"properties":{"arguments":{"type":"object"},"name":{"type":"string"},"tool_use_id":{"$ref":"#/components/schemas/ToolUseId"}}},"PlatformDefaultBudgetSource":{"type":"object","description":"No level published one. There is no row, which is why this is a variant\nand not a null id.","required":["kind"],"properties":{"kind":{"type":"string","enum":["platform_default"]}}},"PolicyBudgetSource":{"type":"object","description":"A published policy won, whole.","required":["id","kind"],"properties":{"id":{"$ref":"#/components/schemas/ContextBudgetPolicyId"},"kind":{"type":"string","enum":["policy"]},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace","description":"The level it was published at. `None` is org-global."}]},"tagged_model":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ModelId","description":"`Some` when the level's tag for this model won over its untagged\npolicy; `None` when the level's untagged policy is what won."}]}}},"Provider":{"type":"string","enum":["anthropic","openai","google","xai","fireworks","openrouter","abliteration"]},"ProviderKeyFellThroughWarning":{"type":"object","description":"The organisation's own provider key failed before any output, and the\nmodel allows falling back, so the turn runs on Twigg's key and is billed\nat the full rate.","required":["key_last4","reason","code"],"properties":{"code":{"type":"string","enum":["provider_key_fell_through"]},"key_last4":{"type":"string"},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace"}]},"reason":{"$ref":"#/components/schemas/LlmErrorKind","description":"How the provider refused the key: `auth`, `rate_limited`, …"}}},"ProviderKeyPausedWarning":{"type":"object","description":"The organisation's own provider key for this model is paused, so the\nturn runs on Twigg's key and is billed at the full rate.","required":["key_last4","code"],"properties":{"code":{"type":"string","enum":["provider_key_paused"]},"key_last4":{"type":"string"},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace","description":"The scope the paused key belongs to. `None` is org-global."}]}}},"PublicPlatformUpdate":{"type":"object","description":"Published site feed: no account-specific read receipts or draft metadata.","required":["id","title","body","kind","important","published_at"],"properties":{"body":{"$ref":"#/components/schemas/UpdateBody"},"id":{"$ref":"#/components/schemas/UpdateId"},"important":{"type":"boolean"},"kind":{"$ref":"#/components/schemas/UpdateKind"},"published_at":{"type":"string","format":"date-time"},"title":{"$ref":"#/components/schemas/UpdateTitle"},"version":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/UpdateVersion"}]}}},"PublishContextBudgetRequest":{"type":"object","description":"Body for publishing a context budget.\n\n`model_ids` is the tag list: one document applied to each of those models,\none version row each. An **empty** list publishes the scope default instead —\nthe budget every model without a tag of its own uses. Publishing again for the same scope and model creates a new version and makes\nit active; the previous version remains available for restoration.","required":["budget"],"properties":{"budget":{"$ref":"#/components/schemas/ContextBudget"},"model_ids":{"type":"array","items":{"$ref":"#/components/schemas/ModelId"}},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace"}]}},"additionalProperties":false},"PublishInstructionRequest":{"type":"object","description":"Body for publishing an instruction. `mode` is ignored on the global scope,\nwhere there is nothing to combine with.","required":["mode","body"],"properties":{"body":{"type":"string"},"mode":{"$ref":"#/components/schemas/ConfigMode"},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace"}]}},"additionalProperties":false},"PublishRetentionPolicyRequest":{"type":"object","description":"Body for publishing a retention policy. `rules` is validated into\n[`RetentionRules`] at the boundary, so an unreachable rule, a truncation that\ncould never cut anything, or an unknown schema version is a 422 before the\nhandler runs.\n\nNo `mode`: a policy is a complete decision table and is selected whole, so\nthere is nothing to combine and nothing to configure about combining.","required":["rules"],"properties":{"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace"}]},"rules":{"$ref":"#/components/schemas/RetentionRules"}},"additionalProperties":false},"PublishToolsRequest":{"type":"object","description":"Body for publishing a tool bundle. `definitions` is validated into a\n[`ToolBundle`] at the boundary, so a malformed bundle is a 422 before the\nhandler runs.","required":["mode","definitions"],"properties":{"definitions":{"type":"array","items":{"$ref":"#/components/schemas/ToolDefinition"}},"mode":{"$ref":"#/components/schemas/ConfigMode"},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace"}]}},"additionalProperties":false},"RatePerMillion":{"type":"string","description":"Price in the stated currency per one million tokens."},"ReasoningBlockStart":{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["reasoning"]}}},"ReasoningCannotBeDisabledWarning":{"type":"object","description":"Reasoning was switched **off** and the provider has no way to express\nthat, so thinking remained enabled.\n\nThe mirror of [`ReasoningNotSupported`](Self::ReasoningNotSupported), and\nthe reason it is a warning rather than something to swallow: the customer\ngets more than they asked for *and is billed for it*. The Responses API\nhas no \"off\" every vendor behind it accepts — the candidates are\nmodel-specific and rejected elsewhere — so omitting the block is the only\nuniversally legal shape, and omitting it means the default applies.\nSilence here would make an explicit `off` look honoured while it quietly\ncosts money on every turn.","required":["model","code"],"properties":{"code":{"type":"string","enum":["reasoning_cannot_be_disabled"]},"model":{"type":"string"}}},"ReasoningDelta":{"type":"object","required":["text","kind"],"properties":{"kind":{"type":"string","enum":["reasoning"]},"text":{"type":"string"}}},"ReasoningEffort":{"type":"string","enum":["off","low","medium","high","x_high","max"]},"ReasoningEffortClampedWarning":{"type":"object","description":"The requested effort tier is above what this model accepts and was\nlowered. The run still happened, at less depth than asked for.","required":["model","requested","applied","code"],"properties":{"applied":{"$ref":"#/components/schemas/ReasoningEffort"},"code":{"type":"string","enum":["reasoning_effort_clamped"]},"model":{"type":"string"},"requested":{"$ref":"#/components/schemas/ReasoningEffort"}}},"ReasoningNotSupportedWarning":{"type":"object","description":"Reasoning was requested but the target model does not support it, so the\nrequest went without a thinking configuration.","required":["model","code"],"properties":{"code":{"type":"string","enum":["reasoning_not_supported"]},"model":{"type":"string"}}},"RecencyThreshold":{"type":"number","format":"float"},"RefusalBlockStart":{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["refusal"]}}},"RefusalDelta":{"type":"object","required":["text","kind"],"properties":{"kind":{"type":"string","enum":["refusal"]},"text":{"type":"string"}}},"ResolvedBudget":{"type":"object","description":"The budget half of a resolution.\n\nSeparate from [`ResolvedConfig`] because it is resolved at a different moment\nand over one axis more: config resolution answers \"what is configured for\nthis namespace\", which a customer can ask without naming a model, while a\nbudget is resolved over namespace *and* model and only means something once a\nrun has picked one.","required":["budget","source","warnings"],"properties":{"budget":{"$ref":"#/components/schemas/ContextBudget","description":"Always present: an org that has published nothing gets the platform\ndefault rather than no budget at all."},"model_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ModelId","description":"The model this was resolved for. `None` asks what an untagged model gets."}]},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace","description":"The scope this was resolved for — what was asked, not what answered.\n[`BudgetSource::Policy::namespace`] is the level that actually supplied\nit, and the two differ whenever a budget is inherited."}]},"source":{"$ref":"#/components/schemas/BudgetSource"},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/ConfigWarning"}}}},"ResolvedConfig":{"type":"object","description":"The resolution result.","required":["tools","retention","estimated_tokens","versions","warnings"],"properties":{"estimated_tokens":{"$ref":"#/components/schemas/TokenEstimate","description":"Instruction plus bundle, as budgeted against. Summed from the frozen\nper-row estimates rather than recomputed, so it matches what the packer\nwill use."},"instructions":{"type":["string","null"],"description":"`None` when neither scope has an active instruction — distinct from an\nempty string, which would be an instruction that says nothing."},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace","description":"The scope this was resolved for. `None` is org-global."}]},"retention":{"$ref":"#/components/schemas/RetentionRules","description":"What a replayed part looks like: which media comes back, how tool\npayloads are truncated, whether reasoning is replayed, what is anchored.\nAlways present — when no scope has published a policy this is the\nplatform default, because \"no configuration\" must not mean \"replay every\nimage forever\".\n\nIt contributes nothing to `estimated_tokens`: a policy is never sent to\na provider, it only decides what of the ledger is, and that cost is\ncounted per part."},"tools":{"type":"array","items":{"$ref":"#/components/schemas/ToolDefinition"}},"versions":{"$ref":"#/components/schemas/ResolvedConfigVersions"},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/ConfigWarning"}}}},"ResolvedConfigVersions":{"type":"object","description":"Which version rows produced a resolution. Persisted on a run's manifest so\n\"what configuration did this request use\" keeps its answer after newer\nversions are published.","required":["instructions","tools"],"properties":{"instructions":{"type":"array","items":{"$ref":"#/components/schemas/SystemInstructionId"},"description":"Every instruction version that contributes, **root first** — the order\nthey are concatenated in.\n\nA list rather than a global/namespace pair. The pair could not express\nthe truth at any depth past one: a chain is arbitrarily deep, every level\non `append` contributes, and a `replace` truncates at whichever level\nissued it. Reporting two ids meant a middle level either vanished from\nthe answer or was misreported as the namespace's."},"retention_policy":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/RetentionPolicyId","description":"One id, not a list: at most one level's retention policy is ever in\nforce, because a policy is selected whole rather than combined."}]},"tools":{"type":"array","items":{"$ref":"#/components/schemas/ToolSchemaId"},"description":"Every tool bundle version that contributes, root first. Same reasoning."}}},"ResponseBody":{"type":"object","description":"A completed turn: the model's output in order, its text concatenated, the tool calls now waiting for results, and the run's usage and cost.","required":["run_id","chat_id","content","text","pending_tool_calls","closed_tool_calls","stop_reason","usage","cost","cost_currency","model_served","provider_response_id","server_tools","compaction","config_warnings","translation_warnings","replayed"],"properties":{"chat_id":{"$ref":"#/components/schemas/ChatId"},"closed_tool_calls":{"type":"array","items":{"$ref":"#/components/schemas/ToolUseId"},"description":"Tool calls this submission closed because they were never answered."},"compaction":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Compaction"}]},"config_warnings":{"type":"array","items":{"$ref":"#/components/schemas/Warning_ConfigWarning"}},"content":{"type":"array","items":{"$ref":"#/components/schemas/ResponseContent"},"description":"Every block the model produced, in order."},"cost":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Money","description":"Settled charge in USD for this response. `null` while settlement is\npending; read it later from `GET /api/v1/runs/{run_id}`."}]},"cost_currency":{"type":"string"},"model_served":{"type":["string","null"],"description":"The model identifier the provider reported, when it reported one. May\ndiffer in spelling from the catalogue name sent in the request."},"pending_tool_calls":{"type":"array","items":{"$ref":"#/components/schemas/PendingToolCallBody"},"description":"Tool calls this turn opened, which the chat now waits on. Send a\n`tool_result` for each in the next request."},"provider_response_id":{"type":["string","null"]},"replayed":{"type":"boolean","description":"`true` when this is the stored result of an earlier request with the\nsame `idempotency_key`, returned instead of running the turn again.\nWarnings and compaction are not stored, so a replay reports none."},"run_id":{"$ref":"#/components/schemas/RunId"},"server_tools":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ServerToolUsage"}]},"stop_reason":{"$ref":"#/components/schemas/StopReason"},"text":{"type":"string","description":"The `text` blocks joined with a blank line. What most integrations map\nstraight into a reply."},"translation_warnings":{"type":"array","items":{"$ref":"#/components/schemas/Warning_TranslationWarning"}},"usage":{"$ref":"#/components/schemas/Usage"}}},"ResponseContent":{"oneOf":[{"$ref":"#/components/schemas/ResponseText"},{"$ref":"#/components/schemas/ResponseReasoning"},{"$ref":"#/components/schemas/ResponseRefusal"},{"$ref":"#/components/schemas/ResponseToolCall"}],"description":"One block of the model's output, in the order the model produced it.","discriminator":{"propertyName":"type","mapping":{"reasoning":"#/components/schemas/ResponseReasoning","refusal":"#/components/schemas/ResponseRefusal","text":"#/components/schemas/ResponseText","tool_call":"#/components/schemas/ResponseToolCall"}}},"ResponseEvent":{"oneOf":[{"$ref":"#/components/schemas/RunEvent"},{"$ref":"#/components/schemas/ConfigWarningsEvent"},{"$ref":"#/components/schemas/TranslationWarningsEvent"},{"$ref":"#/components/schemas/CompactingEvent"},{"$ref":"#/components/schemas/BlockStartEvent"},{"$ref":"#/components/schemas/DeltaEvent"},{"$ref":"#/components/schemas/BlockStopEvent"},{"$ref":"#/components/schemas/DoneEvent"},{"$ref":"#/components/schemas/ErrorEvent"}],"description":"Each variant is one SSE frame: `event: <event>` followed by `data: <JSON>`.\nThe wrapper documents the framing; only its `data` is sent as the JSON payload.","discriminator":{"propertyName":"event","mapping":{"block_start":"#/components/schemas/BlockStartEvent","block_stop":"#/components/schemas/BlockStopEvent","compacting":"#/components/schemas/CompactingEvent","config_warnings":"#/components/schemas/ConfigWarningsEvent","delta":"#/components/schemas/DeltaEvent","done":"#/components/schemas/DoneEvent","error":"#/components/schemas/ErrorEvent","run":"#/components/schemas/RunEvent","translation_warnings":"#/components/schemas/TranslationWarningsEvent"}}},"ResponseReasoning":{"type":"object","description":"Reasoning text the provider exposed. May be empty when the provider\nhides its reasoning.","required":["text","type"],"properties":{"text":{"type":"string"},"type":{"type":"string","enum":["reasoning"]}}},"ResponseRefusal":{"type":"object","description":"A refusal, in place of text.","required":["text","type"],"properties":{"text":{"type":"string"},"type":{"type":"string","enum":["refusal"]}}},"ResponseText":{"type":"object","description":"Text for the user.","required":["text","type"],"properties":{"text":{"type":"string"},"type":{"type":"string","enum":["text"]}}},"ResponseToolCall":{"type":"object","description":"A tool call for the caller to execute. Answer it with a `tool_result`\npart carrying the same `tool_use_id`.","required":["tool_use_id","name","arguments","type"],"properties":{"arguments":{"type":"object","description":"The arguments object. When the model's output did not parse as JSON\n(it was cut off by `max_tokens`, for example), the raw string."},"name":{"type":"string"},"tool_use_id":{"$ref":"#/components/schemas/ToolUseId"},"type":{"type":"string","enum":["tool_call"]}}},"RetentionPolicyId":{"type":"string","format":"uuid"},"RetentionPolicyOverriddenWarning":{"type":"object","description":"A nearer level's retention policy displaced a farther level's. This is how\nthe override is *meant* to work: a policy is a complete decision table and\nis selected whole, so the farther one contributes nothing — not its rules\nand not its defaults. It still warns, because the result looks identical\neither way, and \"my org-wide rule stopped applying\" is otherwise\nundiagnosable.\n\nBoth levels are named because at depth neither is guessable from the\nother: \"a namespace policy won\" does not say which of four ancestors\nstopped applying.","required":["code"],"properties":{"code":{"type":"string","enum":["retention_policy_overridden"]},"displaced":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace","description":"The nearest level whose policy is not being applied."}]},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace","description":"The level whose policy is in force. `None` is org-global."}]}}},"RetentionPolicyResponse":{"allOf":[{"$ref":"#/components/schemas/ConfigVersionResponse"},{"type":"object","required":["rules"],"properties":{"rules":{"$ref":"#/components/schemas/RetentionRules"}}}],"description":"One retention-policy version with its rules.\n\nNo `estimated_tokens`: a policy is never sent to a provider, so unlike an\ninstruction or a bundle it has no token cost of its own. The version envelope\nis shared with the other surfaces, so the field is reported as zero rather\nthan given a separate response shape for one absent number."},"RetentionRules":{"type":"object","description":"The stored document. Private fields: holding one is proof it parsed.","required":["version"],"properties":{"anchor_parts":{"type":"integer","format":"int32","description":"How many parts at the head of the chat are pinned verbatim, never\ncompacted and never truncated. `0` disables it.\n\nCounted in **parts**, not tokens, because the value a customer wants to\nexpress is \"the task spec\", which is a part boundary they can see — not a\ntoken count they would have to estimate and re-tune whenever they edited\nthe spec.","minimum":0},"media":{"$ref":"#/components/schemas/MediaRules"},"reasoning":{"$ref":"#/components/schemas/RecencyThreshold","description":"How recent a part must be for its reasoning to be replayed. Defaults to\nthe same window as media: a reasoning block's replay token is worthless\nto a model of another family anyway, and old reasoning is the least\nload-bearing, most expensive thing in a long agentic history."},"text":{"$ref":"#/components/schemas/TextRules"},"tools":{"$ref":"#/components/schemas/ToolRules"},"verbatim_within":{"$ref":"#/components/schemas/RecencyThreshold","description":"How recent a payload must be to escape truncation entirely — tool results,\ntool arguments and prose alike.\n\nOne setting for the whole document, deliberately, and the direct\ndescendant of the old `truncate_within_frontier` flag. \"Don't cut the tool\noutput I just received\" is not a per-tool judgement, and giving each\nfamily its own would put three definitions of \"recent\" back in a document\nwhose entire point is that there is one.\n\nHoisted out of the tool section when prose truncation arrived: the\nalternative was a second identical field on [`TextRules`], which is how a\nshared metric quietly becomes two that drift."},"version":{"type":"integer","format":"int32","minimum":0}},"additionalProperties":false},"RetryRoute":{"type":"object","description":"A retry runs on the model the failed run used.","required":["kind"],"properties":{"kind":{"type":"string","enum":["retry"]}}},"RouteDecision":{"oneOf":[{"$ref":"#/components/schemas/ChosenRoute"},{"$ref":"#/components/schemas/ToolLoopRoute"},{"$ref":"#/components/schemas/RetryRoute"},{"$ref":"#/components/schemas/FallbackRoute"}],"description":"How a routed turn's model was decided. Reported to the customer, so a\nfallback is never silent.","discriminator":{"propertyName":"kind","mapping":{"chosen":"#/components/schemas/ChosenRoute","fallback":"#/components/schemas/FallbackRoute","retry":"#/components/schemas/RetryRoute","tool_loop":"#/components/schemas/ToolLoopRoute"}}},"RouterFallbackReason":{"type":"string","enum":["not_configured","timeout","unavailable","unknown_model","no_candidates","no_question"]},"RouterId":{"type":"string","format":"uuid"},"RouterVendor":{"type":"string","enum":["telluvian"]},"RunEvent":{"type":"object","description":"Always first: identifiers and tool calls closed by this submission.","required":["data","event"],"properties":{"data":{"$ref":"#/components/schemas/RunEventData"},"event":{"type":"string","enum":["run"]}}},"RunEventData":{"type":"object","description":"Always first: identifiers and tool calls closed by this submission.","required":["run_id","chat_id","closed_tool_calls"],"properties":{"chat_id":{"$ref":"#/components/schemas/ChatId"},"closed_tool_calls":{"type":"array","items":{"$ref":"#/components/schemas/ToolUseId"}},"run_id":{"$ref":"#/components/schemas/RunId"}}},"RunId":{"type":"string","format":"uuid"},"RunInspection":{"type":"object","required":["id","chat_id","namespace","origin","status","is_live","error","model","provider_request_id","usage","latency_ms","cost","settled_at","manifest","created_at","completed_at"],"properties":{"chat_id":{"$ref":"#/components/schemas/ChatId"},"completed_at":{"type":["string","null"],"format":"date-time"},"cost":{"type":["string","null"],"description":"What it was charged, once settled. `None` covers both \"still running\" and\n\"finished but not yet settled\" — a sweep may be seconds or hours behind,\nand the two are the same fact to a reader: no charge has landed yet."},"created_at":{"type":"string","format":"date-time"},"error":{"type":["string","null"],"description":"The failure, when there was one. Present on `failed` runs only."},"id":{"$ref":"#/components/schemas/RunId"},"is_live":{"type":"boolean","description":"Whether a running call has an unexpired durable ownership lease.\nFalse on expiry, before recovery necessarily closes the run. A paused\nworker is indistinguishable from a dead one and is fenced in either case."},"latency_ms":{"type":["integer","null"],"format":"int32"},"manifest":{"type":"object","description":"The context and configuration this call actually used. Opaque JSON on\npurpose: it is a record, not an API — the shape follows what the planner\nhappened to record, and freezing it into typed fields would make every\nplanner change a breaking change here."},"model":{"type":"string","description":"Our catalogue `name`, never the provider's wire string — the same\nidentifier the customer sent and `/api/v1/models` lists."},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace","description":"The scope the run's configuration resolved against. `None` is org-global."}]},"origin":{"$ref":"#/components/schemas/RunOrigin","description":"Whether the customer asked for this call or we did. A `compaction` run is\none the customer never made and is still billed for, which is exactly why\nit is visible here rather than folded into inference."},"provider_request_id":{"type":["string","null"],"description":"The provider's own id for the call, for quoting at us in a support\nconversation. Already visible on the turn's terminal SSE event."},"settled_at":{"type":["string","null"],"format":"date-time"},"status":{"$ref":"#/components/schemas/RunStatus","description":"**The durable answer**, from the `runs` row and never from the cache."},"usage":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Usage","description":"`None` while in flight, or after interruption when usage was lost.\nMissing counts must never be presented as confirmed zero usage."}]}}},"RunOrigin":{"type":"string","enum":["customer","compaction"]},"RunPage":{"type":"object","description":"One page of a chat's runs.","required":["data","first_id","last_id","has_more"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RunSummary"},"description":"Newest first, whichever direction was paged."},"first_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/RunId","description":"Pass as `before_id` to page newer. `null` when the page is empty."}]},"has_more":{"type":"boolean","description":"Whether more runs exist in the direction being paged."},"last_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/RunId","description":"Pass as `after_id` to page older. `null` when the page is empty."}]}}},"RunStatus":{"type":"string","enum":["running","succeeded","failed","cancelled"]},"RunSummary":{"type":"object","description":"One run in a chat's run listing: [`RunInspection`] without the chat it\nbelongs to, which the path already names, and without the manifest, which\ncan be large. `GET /api/v1/runs/{id}` has both.","required":["id","origin","status","is_live","error","model","provider_request_id","usage","latency_ms","cost","settled_at","created_at","completed_at"],"properties":{"completed_at":{"type":["string","null"],"format":"date-time"},"cost":{"type":["string","null"],"description":"What it was charged, once settled."},"created_at":{"type":"string","format":"date-time"},"error":{"type":["string","null"]},"id":{"$ref":"#/components/schemas/RunId"},"is_live":{"type":"boolean"},"latency_ms":{"type":["integer","null"],"format":"int32"},"model":{"type":"string"},"origin":{"$ref":"#/components/schemas/RunOrigin","description":"`compaction` runs are Twigg's own context management on this chat, and\nbilled like the rest."},"provider_request_id":{"type":["string","null"]},"settled_at":{"type":["string","null"],"format":"date-time"},"status":{"$ref":"#/components/schemas/RunStatus"},"usage":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Usage","description":"`None` while in flight, or when an interruption lost the counts."}]}}},"RunUsageGroup":{"type":"object","required":["entry_type","dimension"],"properties":{"api_key_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ApiKeyId"}]},"dimension":{"type":"string","enum":["run"]},"entry_type":{"$ref":"#/components/schemas/BalanceEntryType"},"last_occurred_at":{"type":["string","null"],"format":"date-time","description":"When this run last recorded an event — what the list is ordered by,\nsince a run has no single instant of its own here."},"model_name":{"type":["string","null"]},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace"}]},"run_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/RunId"}]}}},"ServerToolUsage":{"type":"object","description":"Provider-executed operations. Counts are successful billable operations,\ntaken from terminal usage, not inferred from streamed attempts.","required":["document_search_calls"],"properties":{"document_search_calls":{"type":"integer","format":"int32","minimum":0},"provider_cost":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Money","description":"Total provider charge, including tokens, when document tools were used."}]}}},"StopReason":{"type":"string","enum":["end_turn","max_tokens","tool_use","stop_sequence","refusal","aborted"]},"SubmittedMedia":{"type":"object","description":"An inline attachment. Supply standard base64 bytes without a data-URI prefix and the matching MIME type. Model-specific format, byte and count limits apply.","required":["mime","data_base64"],"properties":{"data_base64":{"type":"string","description":"Standard base64, no data-URI prefix.\n\nNamed for its encoding because the field is what a customer has to get\nright, and `data` alone invites a raw string or a `data:` URL — both of\nwhich would decode to something, quietly, and be sealed as an image\nnothing can open."},"filename":{"type":["string","null"],"description":"Shown in a UI, and named in the stub that replaces this attachment once\nretention drops it — which is why it is worth carrying even though no\nprovider requires it."},"mime":{"type":"string","description":"Explicit MIME type, such as `image/png` or `application/pdf`. Validated\nagainst the selected model's configured media capabilities before the\nturn is persisted. Supported formats differ by model and carrier."}},"additionalProperties":false},"SubmittedPart":{"oneOf":[{"$ref":"#/components/schemas/SubmittedPrompt"},{"$ref":"#/components/schemas/SubmittedToolResult"}],"description":"One part the customer is submitting.\n\nOnly the two **user-role** kinds are representable. A customer cannot author\na `message`, a `reasoning` block or a `tool_call` — those come back from a\nmodel — so leaving them out makes the impossible submission unconstructible\nrather than merely rejected, and there is no branch anywhere below that has\nto check for one.","discriminator":{"propertyName":"type","mapping":{"prompt":"#/components/schemas/SubmittedPrompt","tool_result":"#/components/schemas/SubmittedToolResult"}}},"SubmittedPrompt":{"type":"object","description":"The customer's own turn.","required":["type"],"properties":{"client_data":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ClientData","description":"Your own JSON for this part, up to 64 KB. Stored encrypted beside\nit, never sent to a model, and read back from history with\n`include_client_data=true`."}]},"media":{"type":"array","items":{"$ref":"#/components/schemas/SubmittedMedia"}},"text":{"type":"string"},"type":{"type":"string","enum":["prompt"]}}},"SubmittedToolResult":{"type":"object","description":"The answer to a tool call the model made.","required":["tool_use_id","tool_name","type"],"properties":{"client_data":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ClientData","description":"Your own JSON for this part, as on a prompt."}]},"is_error":{"type":"boolean","description":"Anthropic's `tool_result.is_error`. Dropped when translating to a\nprovider with no equivalent."},"media":{"type":"array","items":{"$ref":"#/components/schemas/SubmittedMedia"},"description":"What the tool returned besides text — a screenshot, most often,\nwhich is the canonical case the media tier exists for."},"text":{"type":"string"},"tool_name":{"type":"string","description":"The tool's name, as it was called. Required because Google puts the\nfunction name on the response and nothing else on the row could\nsupply it without joining back to the call."},"tool_use_id":{"$ref":"#/components/schemas/ToolUseId"},"trust":{"$ref":"#/components/schemas/TrustLevel","description":"How far this content is trusted, driving the write-time hygiene\nlimits. Defaults to `customer_data`, the safe assumption."},"type":{"type":"string","enum":["tool_result"]}}},"SystemInstructionId":{"type":"string","format":"uuid"},"SystemPrompt":{"type":"string","maxLength":100000,"minLength":1},"TextBlockStart":{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["text"]}}},"TextDelta":{"type":"object","required":["text","kind"],"properties":{"kind":{"type":"string","enum":["text"]},"text":{"type":"string"}}},"TextRules":{"type":"object","description":"Truncation policies for older user prompts and assistant messages. The current exchange and configured anchor remain protected.","properties":{"message":{"$ref":"#/components/schemas/Truncation","description":"Applied to an assistant `message`'s text.\n\nSeparate from `prompt` for the same reason a tool's arguments and result\nare separate: they are different sizes with different value. A customer\npasting logs wants their own input cut; a customer whose model writes long\nanswers wants the replies cut."},"prompt":{"$ref":"#/components/schemas/Truncation","description":"Applied to a `prompt` part's text."}},"additionalProperties":false},"TierMode":{"type":"string","enum":["cliff","graduated"]},"TokenEstimate":{"type":"integer","format":"int32","description":"A count of estimated tokens. Always non-negative; saturates rather than\noverflowing, because a budget calculation must never wrap into a small\nnumber and wave through a request that cannot fit."},"TombstoneReason":{"type":"string","enum":["abandoned","cancelled","expired"]},"ToolCallBlockStart":{"type":"object","required":["tool_use_id","tool_name","kind"],"properties":{"kind":{"type":"string","enum":["tool_call"]},"tool_name":{"$ref":"#/components/schemas/ToolName"},"tool_use_id":{"$ref":"#/components/schemas/ToolUseId"}}},"ToolDefinition":{"type":"object","description":"A named tool with a description and JSON Schema parameters. Parameters must be a valid schema describing an object; external schema references are not supported.","required":["name","input_schema"],"properties":{"description":{"type":["string","null"]},"input_schema":{"type":"object"},"name":{"$ref":"#/components/schemas/ToolName"},"strict":{"type":["boolean","null"],"description":"Ask the provider to guarantee the tool call validates against the schema.\n\n`None` means the customer did not say, which is distinct from `false`:\nthe providers' own defaults differ, and translating an unstated\npreference into an explicit `false` would silently opt a customer out of\na guarantee they never declined. Dropped when targeting Google, which has\nno equivalent."}}},"ToolFieldDroppedWarning":{"type":"object","description":"A tool definition carried a field the target provider has no equivalent\nfor (Google has no `strict`; only Anthropic has document `title` /\n`context`). Dropped on translation.","required":["tool","field","code"],"properties":{"code":{"type":"string","enum":["tool_field_dropped"]},"field":{"type":"string"},"tool":{"$ref":"#/components/schemas/ToolName"}}},"ToolInputDelta":{"type":"object","required":["text","kind"],"properties":{"kind":{"type":"string","enum":["tool_input"]},"text":{"type":"string"}}},"ToolLoopRoute":{"type":"object","description":"The turn answers tool calls, so it stays on the model that made them.","required":["kind"],"properties":{"kind":{"type":"string","enum":["tool_loop"]}}},"ToolName":{"type":"string"},"ToolNamePattern":{"type":"string"},"ToolRetentionRule":{"allOf":[{"$ref":"#/components/schemas/ToolTreatment"},{"type":"object","required":["tool"],"properties":{"tool":{"$ref":"#/components/schemas/ToolNamePattern"}}}],"description":"One tool rule."},"ToolRules":{"type":"object","description":"The tool section: how tool payloads are cut down.","properties":{"default":{"$ref":"#/components/schemas/ToolTreatment","description":"Applied when no rule matches."},"errors":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Truncation","description":"Replaces the matched `result` treatment on a part flagged `is_error`.\n`None` means errors follow the ordinary rule.\n\nWorth its own knob because failures split the customer base cleanly: for\none, a stack trace is the most valuable thing in the history; for the\nnext, it is a retry loop's worth of noise."}]},"mark_truncations":{"type":"boolean","description":"Whether a cut payload carries a visible marker of what was elided.\n\nDefaults **on**, and deliberately not a per-rule choice: a model that\ncannot tell output was truncated will confidently invent the missing\nmiddle, and that failure is not a per-tool judgement call."},"rules":{"type":"array","items":{"$ref":"#/components/schemas/ToolRetentionRule"}}},"additionalProperties":false},"ToolSchemaId":{"type":"string","format":"uuid"},"ToolSchemaResponse":{"allOf":[{"$ref":"#/components/schemas/ConfigVersionResponse"},{"type":"object","required":["definitions"],"properties":{"definitions":{"type":"array","items":{"$ref":"#/components/schemas/ToolDefinition"}}}}],"description":"One tool-bundle version with its definitions — the single-version shape, the\nsibling of [`InstructionResponse`]. The history endpoint returns bare\n[`ConfigVersionResponse`]s, because definitions are sealed and listing them\nwould be a fetch and a decrypt per row."},"ToolShadowedWarning":{"type":"object","description":"A namespace tool replaced a global tool of the same name. The union is\nkeyed on name, so this is how an override is *meant* to work — but it is\nalso exactly what a typo in a tool name looks like from the outside.","required":["name","namespace","code"],"properties":{"code":{"type":"string","enum":["tool_shadowed"]},"name":{"$ref":"#/components/schemas/ToolName"},"namespace":{"$ref":"#/components/schemas/Namespace"}}},"ToolTreatment":{"type":"object","description":"How one tool's two payloads are treated. Arguments and results are separate\nbecause they are separate parts with separate sizes — a `write_file` call's\narguments routinely dwarf its result, and a `search` call's result dwarfs its\narguments.","properties":{"arguments":{"$ref":"#/components/schemas/Truncation","description":"Applied to the `tool_call` arguments."},"result":{"$ref":"#/components/schemas/Truncation","description":"Applied to the `tool_result` payload."}},"additionalProperties":false},"ToolUseId":{"type":"string"},"TranslationWarning":{"oneOf":[{"$ref":"#/components/schemas/MediaLimitExceededWarning"},{"$ref":"#/components/schemas/MediaUnsupportedWarning"},{"$ref":"#/components/schemas/ReasoningNotSupportedWarning"},{"$ref":"#/components/schemas/ReasoningCannotBeDisabledWarning"},{"$ref":"#/components/schemas/ReasoningEffortClampedWarning"},{"$ref":"#/components/schemas/ToolFieldDroppedWarning"},{"$ref":"#/components/schemas/ForeignArtifactsStrippedWarning"}],"discriminator":{"propertyName":"code","mapping":{"foreign_artifacts_stripped":"#/components/schemas/ForeignArtifactsStrippedWarning","media_limit_exceeded":"#/components/schemas/MediaLimitExceededWarning","media_unsupported":"#/components/schemas/MediaUnsupportedWarning","reasoning_cannot_be_disabled":"#/components/schemas/ReasoningCannotBeDisabledWarning","reasoning_effort_clamped":"#/components/schemas/ReasoningEffortClampedWarning","reasoning_not_supported":"#/components/schemas/ReasoningNotSupportedWarning","tool_field_dropped":"#/components/schemas/ToolFieldDroppedWarning"}}},"TranslationWarningsEvent":{"type":"object","description":"Model compatibility warnings before content starts.","required":["data","event"],"properties":{"data":{"$ref":"#/components/schemas/TranslationWarningsEventData"},"event":{"type":"string","enum":["translation_warnings"]}}},"TranslationWarningsEventData":{"type":"object","description":"Model compatibility warnings before content starts.","required":["warnings"],"properties":{"warnings":{"type":"array","items":{"$ref":"#/components/schemas/Warning_TranslationWarning"}}}},"Truncation":{"oneOf":[{"$ref":"#/components/schemas/TruncationKeep"},{"$ref":"#/components/schemas/TruncationAlways"},{"$ref":"#/components/schemas/TruncationOver"}],"description":"Keep content unchanged, always truncate to a token target, or truncate only when it exceeds a threshold. Choose the head, tail, or both ends to retain.","discriminator":{"propertyName":"mode","mapping":{"always":"#/components/schemas/TruncationAlways","keep":"#/components/schemas/TruncationKeep","over":"#/components/schemas/TruncationOver"}}},"TruncationAlways":{"type":"object","description":"Always cut to `to` tokens.","required":["to","mode"],"properties":{"keep":{"$ref":"#/components/schemas/TruncationShape"},"mode":{"type":"string","enum":["always"]},"to":{"$ref":"#/components/schemas/TokenEstimate"}}},"TruncationKeep":{"type":"object","description":"Replay it whole, however large.","required":["mode"],"properties":{"mode":{"type":"string","enum":["keep"]}}},"TruncationOver":{"type":"object","description":"Cut to `to` tokens, but only once the payload exceeds `over`. The common\nshape: small results replay verbatim, a runaway one is clipped.","required":["over","to","mode"],"properties":{"keep":{"$ref":"#/components/schemas/TruncationShape"},"mode":{"type":"string","enum":["over"]},"over":{"$ref":"#/components/schemas/TokenEstimate"},"to":{"$ref":"#/components/schemas/TokenEstimate"}}},"TruncationShape":{"type":"string","enum":["head","tail","head_and_tail"]},"TrustLevel":{"type":"string","enum":["trusted","customer_data","untrusted"]},"UpdateBody":{"type":"string"},"UpdateChatRequest":{"type":"object","description":"Body for [`update`]. Every field is optional, and a field left out is left\nalone.\n\n`title` and `description` sent as `null` or `\"\"` are removed, the same\ncoercion create applies, so clearing a form field clears the label.\n`namespace` and `external_id` are not here and are refused as unknown\nfields rather than ignored: a client that sent one expected it to change.","properties":{"description":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChatDescription"}]},"title":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChatTitle"}]},"user_metadata":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/UserMetadataPatch","description":"Merged into the stored value one top-level key at a time. A key sent as\n`null` is removed. Sending `null` for the whole field changes nothing."}]}},"additionalProperties":false},"UpdateId":{"type":"string","format":"uuid"},"UpdateKind":{"type":"string","enum":["release","notice","maintenance"]},"UpdateTitle":{"type":"string"},"UpdateVersion":{"type":"string"},"Uptime":{"type":"string","description":"A measured ratio from 0 to 1; multiply by 100 to display a percentage."},"Usage":{"type":"object","required":["input_tokens","output_tokens","cache_read_tokens","cache_write_tokens","reasoning_tokens"],"properties":{"cache_read_tokens":{"type":"integer","format":"int32","description":"Served from the provider's prompt cache, billed below base rate.","minimum":0},"cache_write_tokens":{"type":"integer","format":"int32","description":"Written to the provider's prompt cache, billed above base rate. The\nResponses API does not meter this and reports zero.","minimum":0},"input_tokens":{"type":"integer","format":"int32","description":"Billable input at the base rate. Excludes both cache figures.","minimum":0},"output_tokens":{"type":"integer","format":"int32","description":"Everything the model produced, reasoning included.","minimum":0},"reasoning_tokens":{"type":"integer","format":"int32","description":"The thinking share of [`Self::output_tokens`]. **A subset, not an\naddition** — reported for visibility, never summed into the total.","minimum":0}}},"UsageBin":{"type":"string","enum":["hour","day"]},"UsageDimension":{"type":"string","enum":["model","namespace","api_key","entry_type","organisation","run"]},"UsageGroup":{"oneOf":[{"$ref":"#/components/schemas/ModelUsageGroup"},{"$ref":"#/components/schemas/NamespaceUsageGroup"},{"$ref":"#/components/schemas/ApiKeyUsageGroup"},{"$ref":"#/components/schemas/OrganisationUsageGroup"},{"$ref":"#/components/schemas/EntryTypeUsageGroup"},{"$ref":"#/components/schemas/RunUsageGroup"}],"description":"Which slice a row is, and everything needed to label it.\n\nA tagged union rather than a `key: String`, because the labels are not\ninterchangeable: a model row needs the id *and* the human name, a namespace\nrow's key can legitimately be absent (the org-global scope), and a run row\ncarries the context you would drill from.","discriminator":{"propertyName":"dimension","mapping":{"api_key":"#/components/schemas/ApiKeyUsageGroup","entry_type":"#/components/schemas/EntryTypeUsageGroup","model":"#/components/schemas/ModelUsageGroup","namespace":"#/components/schemas/NamespaceUsageGroup","organisation":"#/components/schemas/OrganisationUsageGroup","run":"#/components/schemas/RunUsageGroup"}}},"UsageReport":{"type":"object","description":"A report: the rows, plus the shape of the question they answer.\n\nThe window is echoed because it is not what the caller literally asked for —\na range preset is resolved against the clock and rounded to the hour — and a\nchart that cannot state its own axis is a chart nobody can check.","required":["window","rows","cached"],"properties":{"bin":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/UsageBin"}]},"cached":{"type":"boolean","description":"Whether these rows came from the cache. Surfaced rather than hidden: the\nconsole tells the customer their usage lags by minutes, and this is the\nhonest version of that sentence."},"group_by":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/UsageDimension"}]},"namespace":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Namespace"}]},"rows":{"type":"array","items":{"$ref":"#/components/schemas/UsageRow"}},"window":{"$ref":"#/components/schemas/UsageWindow"}}},"UsageRow":{"allOf":[{"$ref":"#/components/schemas/UsageTotals"},{"type":"object","properties":{"bucket":{"type":["string","null"],"format":"date-time"},"group":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/UsageGroup"}]}}}],"description":"One row of a report: an optional bucket, an optional group, and the measures.\n\nBoth are `Option` because the same row type serves all four query shapes, and\nwhich of them are populated is a property of the query rather than of the\nrow — the report echoes the query shape beside the rows so a reader never has\nto infer it."},"UsageTotals":{"type":"object","description":"The measures every row carries, whatever it is grouped by.\n\n`runs` counts **distinct run ids**, not events: a run that was compacted\nproduces two events naming it, and counting rows would report the busy runs\ntwice. Credits share the analytics source table but are excluded from this\nusage report.","required":["runs","input_tokens","output_tokens","cache_read_tokens","cache_write_tokens","reasoning_tokens","cost"],"properties":{"cache_read_tokens":{"type":"integer","format":"int64"},"cache_write_tokens":{"type":"integer","format":"int64"},"cost":{"$ref":"#/components/schemas/Money","description":"Model-call spend in the requested window. Credits share the source table\nbut are excluded from usage reports."},"input_tokens":{"type":"integer","format":"int64"},"output_tokens":{"type":"integer","format":"int64"},"reasoning_tokens":{"type":"integer","format":"int64","description":"A subset of `output_tokens`, never an addition — and priced at zero, so\nit explains a cost rather than adding to it."},"runs":{"type":"integer","format":"int64"}}},"UsageWindow":{"type":"object","description":"A validated `[from, to)` range over `occurred_at`.\n\nHalf-open, so consecutive windows tile without double-counting the instant\non the boundary — an event at exactly midnight belongs to one day, not two.","required":["from","to"],"properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"UserMetadata":{"type":"object","description":"Customer JSON object, at most 1024 bytes when serialized compactly. Defaults to an empty object."},"UserMetadataPatch":{"type":"object","description":"Keys to set on the chat's user_metadata. A key sent as null is removed; keys left out are kept. Each value replaces the stored one whole, nested objects included. The merged result must be at most 1024 bytes when serialized compactly."},"Warning_ConfigWarning":{"allOf":[{"oneOf":[{"$ref":"#/components/schemas/ToolShadowedWarning"},{"$ref":"#/components/schemas/GlobalInstructionReplacedWarning"},{"$ref":"#/components/schemas/GlobalToolsReplacedWarning"},{"$ref":"#/components/schemas/RetentionPolicyOverriddenWarning"},{"$ref":"#/components/schemas/ContextBudgetResolvedAtWarning"},{"$ref":"#/components/schemas/HistoryDroppedWarning"},{"$ref":"#/components/schemas/ProviderKeyPausedWarning"},{"$ref":"#/components/schemas/ProviderKeyFellThroughWarning"},{"$ref":"#/components/schemas/ModelRoutedWarning"}],"description":"Something legal but worth saying out loud."},{"type":"object","required":["message"],"properties":{"message":{"type":"string"}}}]},"Warning_TranslationWarning":{"allOf":[{"oneOf":[{"$ref":"#/components/schemas/MediaLimitExceededWarning"},{"$ref":"#/components/schemas/MediaUnsupportedWarning"},{"$ref":"#/components/schemas/ReasoningNotSupportedWarning"},{"$ref":"#/components/schemas/ReasoningCannotBeDisabledWarning"},{"$ref":"#/components/schemas/ReasoningEffortClampedWarning"},{"$ref":"#/components/schemas/ToolFieldDroppedWarning"},{"$ref":"#/components/schemas/ForeignArtifactsStrippedWarning"}]},{"type":"object","required":["message"],"properties":{"message":{"type":"string"}}}]}},"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer"}}}}