{"openapi":"3.1.0","info":{"title":"Pistis HTTP API","version":"1","description":"Start, follow and steer agent sessions. Send an API token as `Authorization: Bearer <token>`; it sees only its own person's sessions. Errors are `{ error, code }`.","license":{"name":"Apache-2.0","identifier":"Apache-2.0"}},"servers":[{"url":"{origin}","variables":{"origin":{"default":"http://127.0.0.1:7777","description":"Your Pistis server"}}}],"security":[{"bearer":[]}],"tags":[{"name":"Sessions"},{"name":"Messages"},{"name":"Following"},{"name":"Approvals and questions"},{"name":"Changing a session"},{"name":"Sharing"},{"name":"Flows"},{"name":"Connections"},{"name":"People and roles","description":"Roles and who has which (U92): an admin area, People & roles"},{"name":"MCP","description":"Pistis as an OAuth-protected MCP server: its metadata and authorization server (U81)"},{"name":"Webhooks"},{"name":"Server"}],"paths":{"/sessions":{"post":{"operationId":"createSession","summary":"Start a session","description":"`requestId` is any string you choose: sending the same one again returns the same session. `meta` labels it (and picks an agent, repositories or a pool); `agent` changes this session's agent from the host's defaults.","tags":["Sessions"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"requestId":{"type":"string"},"meta":{"$ref":"#/components/schemas/SessionMeta"},"agent":{"$ref":"#/components/schemas/AgentSpec"}},"required":[],"additionalProperties":false},"example":{"requestId":"my-first"}}}},"responses":{"200":{"description":"The session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionInfo"}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is over 1048576 bytes (`too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listSessions","summary":"List your sessions","description":"Oldest first, a page at a time. Filter by label with `meta.<key>=<value>` (every one given must match).","tags":["Sessions"],"parameters":[{"name":"ended","in":"query","description":"`1` only ended, `0` only open","schema":{"type":"string","enum":["1","0","true","false"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}},{"name":"after","in":"query","description":"The `next` of the previous page","schema":{"type":"string"}},{"name":"shared","in":"query","description":"`1`: sessions shared with you","schema":{"type":"string"}},{"name":"all","in":"query","description":"`1`: everyone's (admins)","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of sessions","content":{"application/json":{"schema":{"type":"object","properties":{"sessions":{"type":"array","items":{"$ref":"#/components/schemas/SessionInfo"}},"next":{"type":"string","description":"Pass as `after` for the next page"}},"required":["sessions"],"additionalProperties":false}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}":{"get":{"operationId":"getSession","summary":"Read a session","tags":["Sessions"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"The session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionInfo"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"endSession","summary":"End a session","description":"Deletes its sandbox and keeps the conversation. Ending twice is fine.","tags":["Sessions"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"Ended","content":{"application/json":{"schema":{"type":"object","properties":{"ended":{"const":true}},"required":["ended"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/messages":{"post":{"operationId":"sendMessage","summary":"Send a message","description":"The same `idempotencyKey` is accepted once. While a turn runs, `whenBusy` `followUp` (default) waits for it to end and `steer` joins it. `attachments` are ids from the attachments route. Wait for the turn with the submissions route, or follow the events.","tags":["Messages"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"input":{"type":"string"},"idempotencyKey":{"type":"string"},"mode":{"$ref":"#/components/schemas/InputMode"},"whenBusy":{"type":"string","enum":["followUp","steer"]},"attachments":{"type":"array","items":{"type":"string","description":"`att_<hex>`"}}},"required":["input","idempotencyKey"],"additionalProperties":false},"example":{"input":"run: ls -la /workspace","idempotencyKey":"msg-1"}}}},"responses":{"200":{"description":"Accepted","content":{"application/json":{"schema":{"type":"object","properties":{"submissionId":{"type":"string"}},"required":["submissionId"],"additionalProperties":false}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The session ended (`session_ended`) or is busy (`busy`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is over 1048576 bytes (`too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/pending":{"get":{"operationId":"listPending","summary":"List waiting messages","description":"Messages a turn has not taken yet, oldest first. They run in that order.","tags":["Messages"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"Waiting messages","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PendingItem"}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/pending/{sid}":{"delete":{"operationId":"withdrawMessage","summary":"Withdraw a waiting message","description":"Drops one message a turn has not taken yet. Withdrawing it twice is fine.","tags":["Messages"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"},{"name":"sid","in":"path","required":true,"description":"A submission id","schema":{"type":"string"},"example":"sub_1"}],"responses":{"204":{"description":"Withdrawn"},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A turn already took it, or the session ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/submissions/{sid}":{"get":{"operationId":"waitForTurn","summary":"Wait for a message's turn","description":"Holds the request until the turn that took the message ends, for up to 25 seconds; then 202: ask again.","tags":["Messages"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"},{"name":"sid","in":"path","required":true,"description":"A submission id","schema":{"type":"string"},"example":"sub_1"}],"responses":{"200":{"description":"The turn ended: `done`, or `unanswered` with why","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Settled"}}}},"202":{"description":"Still running: ask again","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"const":"pending"}},"required":["status"],"additionalProperties":false}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/attachments":{"post":{"operationId":"attachFile","summary":"Attach a file","description":"The file as the raw body with its media type and its name in `x-filename`, or a multipart form. Up to 10 MB a file and 25 MB a message. Send its id with a message.","tags":["Messages"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"},{"name":"x-filename","in":"header","description":"The file's name (URL-encoded), for a raw body","schema":{"type":"string"},"example":"notes.txt"}],"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"},"example":"hello"},"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"],"additionalProperties":false}}}},"responses":{"200":{"description":"Attached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Attachment"}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The session ended (`session_ended`) or is busy (`busy`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is over 1048576 bytes (`too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/attachments/{aid}":{"get":{"operationId":"getAttachment","summary":"Download an attachment","description":"The file's bytes, with its media type. Images are shown inline; anything else downloads.","tags":["Messages"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"},{"name":"aid","in":"path","required":true,"description":"An attachment id","schema":{"type":"string"},"example":"att_0f1e2d3c"}],"responses":{"200":{"description":"The file","content":{"*/*":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/transcript":{"get":{"operationId":"getTranscript","summary":"Read the conversation","tags":["Following"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"},{"name":"after","in":"query","description":"Only entries after this `seq`","schema":{"type":"integer","minimum":0},"example":0}],"responses":{"200":{"description":"Entries in order","content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/TranscriptEntry"}}},"required":["entries"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/events":{"get":{"operationId":"followSession","summary":"Follow a session live","description":"A server-sent event stream. Each transcript entry is an `entry` event with `id: <seq>`; approvals, questions, waiting messages, status and usage arrive as `approval`, `ask`, `pending`, `status` and `usage` events, each `data` a `SessionEvent`. While the model writes, `reply` events carry its text as it streams (an id, an offset and the text from there; offset 0 is the whole text so far, which a stream opened mid-reply gets first): live only, never replayed, ended by the assistant entry itself. Reconnect with `Last-Event-ID` (or `?after=`) to get every later entry exactly once. A stream that has to end says why in an `error` event.","tags":["Following"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"},{"name":"after","in":"query","description":"Start after this `seq`","schema":{"type":"integer","minimum":0}},{"name":"Last-Event-ID","in":"header","description":"Resume after this `seq`","schema":{"type":"string"}}],"responses":{"200":{"description":"`text/event-stream`; each event's `data` is a `SessionEvent`","content":{"text/event-stream":{"schema":{"type":"string"},"x-pistis-event":{"$ref":"#/components/schemas/SessionEvent"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/status":{"get":{"operationId":"getStatus","summary":"Read what a session is doing","tags":["Following"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"Its status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStatus"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/usage":{"get":{"operationId":"getUsage","summary":"Read what a session spent","tags":["Following"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"Tokens and dollars, in total and by model","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionUsage"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/children":{"get":{"operationId":"listChildren","summary":"List subagent sessions","description":"The sessions its `subagent` steps started.","tags":["Following"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"Its children","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Child"}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/sandbox":{"get":{"operationId":"getSandbox","summary":"Read where its sandbox is","description":"Reading it never starts, resumes or replaces a sandbox.","tags":["Following"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"The sandbox's state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxStatus"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/screen":{"get":{"operationId":"watchScreen","summary":"Watch the sandbox's screen","description":"`multipart/x-mixed-replace; boundary=pistis-frame`, for as long as you read it. Each part is a picture (`image/jpeg`, with `X-Screen-Width` and `X-Screen-Height` when known), sent only when the screen changed, or `application/json` `{\"none\": \"<why>\"}` while there is no picture (no browser open yet, the agent isn't using the sandbox). The sandbox makes pictures only while someone watches; a slow reader gets the newest picture, never a backlog. Nothing is recorded. Whoever may read the session may watch it.","tags":["Following"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"`multipart/x-mixed-replace`: JPEG pictures and JSON notes","content":{"multipart/x-mixed-replace":{"schema":{"type":"string"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/control":{"get":{"operationId":"getScreenControl","summary":"Who controls the screen","tags":["Following"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"The agent, or a person until `until`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScreenControl"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"takeOverScreen","summary":"Take over the screen","description":"You control the sandbox's screen until you hand it back or have been gone for the server's `screen.returnAfter`; asking again renews it. The agent's screen actions wait meanwhile, durably. The session's owner or an admin may. 409 while someone else controls it, or when the agent's screen action in flight doesn't end within 15 s.","tags":["Changing a session"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"You control it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScreenControl"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The session ended (`session_ended`) or is busy (`busy`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/control/return":{"post":{"operationId":"handBackScreen","summary":"Hand the screen back","description":"Control returns to the agent; `note` reaches it as your next message (once, however often you ask). The record shows who took over, for how long, and the note; never what was typed or shown.","tags":["Changing a session"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","description":"For the agent, at most 4000 characters"}},"required":[],"additionalProperties":false},"example":{"note":"Signed in; carry on from the dashboard."}}}},"responses":{"200":{"description":"The agent controls it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScreenControl"}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/screen/input":{"post":{"operationId":"screenInput","summary":"Click or type on the screen","description":"One input for the sandbox's browser, from the person in control (403 from anyone else). Send them one at a time, in order. Never recorded.","tags":["Changing a session"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"input":{"$ref":"#/components/schemas/ScreenInput"}},"required":["input"],"additionalProperties":false},"example":{"input":{"type":"mouse","action":"down","x":640,"y":400}}}}},"responses":{"204":{"description":"Sent to the screen"},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/approvals":{"get":{"operationId":"listApprovals","summary":"List waiting approvals","tags":["Approvals and questions"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"Waiting approvals by key","content":{"application/json":{"schema":{"type":"object","properties":{"pending":{"type":"object","additionalProperties":{"type":"object","properties":{"tool":{"type":"string"},"args":{"type":"string","description":"JSON, cut for display"},"requestedAt":{"type":"integer","description":"Asked (milliseconds since the epoch)"}},"required":["tool","args","requestedAt"],"additionalProperties":false}}},"required":["pending"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/approvals/{key}":{"post":{"operationId":"decideApproval","summary":"Approve or deny a step","tags":["Approvals and questions"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"},{"name":"key","in":"path","required":true,"description":"An approval key","schema":{"type":"string"},"example":"17"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"approved":{"type":"boolean"}},"required":["approved"],"additionalProperties":false},"example":{"approved":true}}}},"responses":{"200":{"description":"Decided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"You may not decide in this session (`not_principal`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session (`unknown_session`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Nothing waits on this key, or it was decided (`not_pending`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is over 1048576 bytes (`too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/asks":{"get":{"operationId":"listAsks","summary":"List the agent's questions","tags":["Approvals and questions"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"Questions waiting for an answer","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Ask"}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/asks/{askId}":{"post":{"operationId":"answerAsk","summary":"Answer the agent's question","tags":["Approvals and questions"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"},{"name":"askId","in":"path","required":true,"description":"An ask id","schema":{"type":"string"},"example":"ask_1"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"answer":{"type":"string"}},"required":["answer"],"additionalProperties":false},"example":{"answer":"Use the staging database"}}}},"responses":{"200":{"description":"Answered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Already answered (`answered`), or the session ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is over 1048576 bytes (`too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/retry":{"post":{"operationId":"retryStep","summary":"Run a step again","description":"Runs one earlier tool call again, with the same tool and arguments, as a step of its own; the model sees its result on the next turn. Only while the session is idle. The same `toolCallId` and `idempotencyKey` run it once.","tags":["Changing a session"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"toolCallId":{"type":"string","description":"An earlier step"},"idempotencyKey":{"type":"string"}},"required":["toolCallId","idempotencyKey"],"additionalProperties":false},"example":{"toolCallId":"call_1","idempotencyKey":"retry-1"}}}},"responses":{"200":{"description":"Running again","content":{"application/json":{"schema":{"type":"object","properties":{"toolCallId":{"type":"string","description":"The new step"}},"required":["toolCallId"],"additionalProperties":false}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A turn runs or a message waits (`busy`), or the session ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is over 1048576 bytes (`too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/branch":{"post":{"operationId":"branchSession","summary":"Branch a session","description":"A new session with the conversation up to `atSeq`, and the files as they were then.","tags":["Changing a session"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"atSeq":{"type":"integer","minimum":1,"description":"The last entry to keep"},"requestId":{"type":"string"}},"required":["atSeq"],"additionalProperties":false},"example":{"atSeq":1}}}},"responses":{"200":{"description":"The new session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionInfo"}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The session ended (`session_ended`) or is busy (`busy`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is over 1048576 bytes (`too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/model":{"post":{"operationId":"switchModel","summary":"Switch a session's model","description":"From its next model call on. Without `thinking`, the level stays if the model takes it, else `off`.","tags":["Changing a session"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"model":{"type":"string","description":"`provider/model-id`"},"thinking":{"$ref":"#/components/schemas/ThinkingLevel"}},"required":["model"],"additionalProperties":false},"example":{"model":"demo/demo"}}}},"responses":{"200":{"description":"What it runs on now","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionModel"}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The session ended (`session_ended`) or is busy (`busy`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is over 1048576 bytes (`too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/cancel":{"post":{"operationId":"stopSession","summary":"Stop the turn","description":"Stops the turn and drops waiting messages. On a flow run's own session it also stops the run and every session it started.","tags":["Changing a session"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"Stopped","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The session ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/parked":{"get":{"operationId":"listParkedSteps","summary":"List steps stopped after repeated crashes","description":"Steps the server stopped running because a crash cut them off five times in a row. They wait until someone retries them. Empty when nothing is stopped.","tags":["Changing a session"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"Stopped steps","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ParkedStep"}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/parked/retry":{"post":{"operationId":"retryParkedSteps","summary":"Retry steps stopped after repeated crashes","description":"Runs the session's stopped steps again. A tool call a crash cut off while it ran is reported as outcome unknown and never run again; one that waited for approval waits again. The session's owner or an admin may.","tags":["Changing a session"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"Retried","content":{"application/json":{"schema":{"type":"object","properties":{"retried":{"type":"integer","description":"How many steps run again (0 when none was stopped)"}},"required":["retried"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/decisions":{"get":{"operationId":"listDecisions","summary":"List the decisions people made in a session","description":"Every decision a person made that shaped the work, newest first: approvals and denials (the exact call), answers to the agent's questions, take-overs of the screen (how long, the note), annotations, retried stopped steps, pauses. Read from the session's own record, so a later message can't change it. Whoever may view the session may.","tags":["Following"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"Decisions, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Decision"}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/pause":{"post":{"operationId":"pauseSession","summary":"Pause the agent","description":"The step running finishes (a tool call is never cut off) and no further step starts until someone resumes; messages sent meanwhile wait. Kept across restarts. Pausing a paused session changes nothing. The owner, a collaborator, or whoever may manage sessions may.","tags":["Changing a session"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"Paused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PauseState"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"resumeSession","summary":"Resume the agent","description":"The agent goes on where it stopped, then takes the messages that waited.","tags":["Changing a session"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"Resumed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PauseState"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/title":{"post":{"operationId":"renameSession","summary":"Rename the session","description":"Sets the session's name (`meta.title`, one line, at most 120 characters) and notes who did. A name a person gave stays: the agent's own naming doesn't replace it. The owner, a collaborator, or whoever may manage sessions may.","tags":["Changing a session"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"}},"required":["title"],"additionalProperties":false},"example":{"title":"Raise the login timeout"}}}},"responses":{"200":{"description":"Renamed","content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"}},"required":["title"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/models":{"get":{"operationId":"listModels","summary":"List the models you may pick","tags":["Sessions"],"responses":{"200":{"description":"Models","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ModelInfo"}},"default":{"type":"string","description":"What a new session gets; absent while no provider has a key"}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/repos":{"get":{"operationId":"findRepos","summary":"Find repositories you may use","description":"Repositories you may start a session on (`meta.repo`), matching `q` anywhere in the path, the exact name first; without `q`, the ones you used last first. A page at a time.","tags":["Sessions"],"parameters":[{"name":"q","in":"query","description":"Part of the path","schema":{"type":"string"},"example":"api"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100},"example":20},{"name":"cursor","in":"query","description":"The `next` of the previous page","schema":{"type":"string"}}],"responses":{"200":{"description":"Matching repositories","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/RepoChoice"}},"next":{"type":"string","description":"Pass as `cursor` for the next page"}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/shares":{"get":{"operationId":"listShares","summary":"List who a session is shared with","description":"Needs a person's token and the right to share the session.","tags":["Sharing"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"responses":{"200":{"description":"People and links","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Grant"}},"links":{"type":"array","items":{"$ref":"#/components/schemas/ShareLink"}}},"required":["items","links"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"shareSession","summary":"Share a session with a person","tags":["Sharing"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"with":{"type":"string","description":"The person's email or name"},"role":{"$ref":"#/components/schemas/ShareRole"}},"required":["with","role"],"additionalProperties":false},"example":{"with":"bob@example.com","role":"viewer"}}}},"responses":{"200":{"description":"Shared","content":{"application/json":{"schema":{"type":"object","properties":{"with":{"type":"string","description":"Their principal"},"role":{"$ref":"#/components/schemas/ShareRole"}},"required":["with","role"],"additionalProperties":false}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is over 1048576 bytes (`too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/shares/{who}":{"delete":{"operationId":"unshareSession","summary":"Stop sharing with a person","description":"They lose access at once.","tags":["Sharing"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"},{"name":"who","in":"path","required":true,"description":"Their email, name or principal","schema":{"type":"string"},"example":"bob@example.com"}],"responses":{"204":{"description":"Revoked"},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/links":{"post":{"operationId":"createLink","summary":"Make a read-only link","description":"Anyone with the URL can watch the session without signing in until it expires. The URL is shown only this once.","tags":["Sharing"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"expiresInSeconds":{"type":"integer","minimum":1,"description":"Default 7 days, at most 30"}},"required":[],"additionalProperties":false},"example":{"expiresInSeconds":86400}}}},"responses":{"200":{"description":"The link","content":{"application/json":{"schema":{"type":"object","properties":{"linkId":{"type":"string"},"role":{"const":"viewer"},"expiresAt":{"type":"integer","description":"Expires (milliseconds since the epoch)"},"url":{"type":"string"}},"required":["linkId","role","expiresAt","url"],"additionalProperties":false}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is over 1048576 bytes (`too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}/links/{linkId}":{"delete":{"operationId":"revokeLink","summary":"Revoke a link","tags":["Sharing"],"parameters":[{"name":"id","in":"path","required":true,"description":"A session id","schema":{"type":"string"},"example":"ses_6c1f2a0b9d3e4f5a6b7c"},{"name":"linkId","in":"path","required":true,"description":"A link id","schema":{"type":"string"},"example":"lnk_1"}],"responses":{"204":{"description":"Revoked"},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The session is moving to another server; try again (`unavailable`, with `retry-after`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/shared/{token}":{"get":{"operationId":"readSharedLink","summary":"Read a session through a link","description":"No API token: the link is the credential. It only reads.","tags":["Sharing"],"security":[],"parameters":[{"name":"token","in":"path","required":true,"description":"The link's token, from its URL","schema":{"type":"string"},"example":"Zm9vYmFyYmF6cXV4cXV1eA"}],"responses":{"200":{"description":"The session","content":{"application/json":{"schema":{"type":"object","properties":{"session":{"$ref":"#/components/schemas/SessionInfo"},"role":{"const":"viewer"},"entries":{"type":"array","items":{"$ref":"#/components/schemas/TranscriptEntry"}}},"required":["session","role","entries"],"additionalProperties":false}}}},"404":{"description":"No such link, or it expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"A link only reads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/flows":{"get":{"operationId":"listFlows","summary":"List flows","tags":["Flows"],"responses":{"200":{"description":"File flows, and flows built in the web app or from a chat (with `built`, and who saved it)","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/FlowSummary"}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/flows/{flowId}":{"put":{"operationId":"saveFlow","summary":"Build or change a flow","description":"Admins only, with a person's token, saved as that person (listed as `saved`). The next run takes the new steps; a run already going keeps its own. An agent proposes one with its `save_flow` tool: a waiting approval whose approval (`POST /sessions/{id}/approvals/{key}`, by someone who may build flows) saves it.","tags":["Flows"],"parameters":[{"name":"flowId","in":"path","required":true,"description":"`^[a-z0-9][a-z0-9-]{0,63}$`","schema":{"type":"string"},"example":"nightly-check"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"on":{"$ref":"#/components/schemas/FlowTrigger"},"steps":{"type":"array","items":{"type":"string"}},"repos":{"type":"array","items":{"type":"string"}},"concurrency":{"type":"integer"}},"required":["on","steps"],"additionalProperties":false},"example":{"on":{"manual":true},"steps":["run: pnpm test"]}}}},"responses":{"200":{"description":"Saved","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"flow":{"$ref":"#/components/schemas/FlowSpec"}},"required":["ok","flow"],"additionalProperties":false}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is over 1048576 bytes (`too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"removeFlow","summary":"Remove a built flow","description":"Admins only. Its runs stay ordinary sessions. A flow file can't be removed this way.","tags":["Flows"],"parameters":[{"name":"flowId","in":"path","required":true,"description":"A flow id","schema":{"type":"string"},"example":"nightly-check"}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/flows/{flowId}/runs":{"get":{"operationId":"listFlowRuns","summary":"List a flow's runs","description":"The newest 50, newest first.","tags":["Flows"],"parameters":[{"name":"flowId","in":"path","required":true,"description":"A flow id","schema":{"type":"string"},"example":"nightly-check"}],"responses":{"200":{"description":"Runs","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/FlowRun"}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"startFlowRun","summary":"Start a flow run","description":"The same `runId` returns the same run. Follow the run's session like any other.","tags":["Flows"],"parameters":[{"name":"flowId","in":"path","required":true,"description":"A flow id","schema":{"type":"string"},"example":"nightly-check"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"payload":{},"runId":{"type":"string","description":"`^[A-Za-z0-9_-]{1,100}$`"}},"required":[],"additionalProperties":false},"example":{"runId":"run-1"}}}},"responses":{"200":{"description":"Started","content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"string"},"sessionId":{"type":"string"}},"required":["runId","sessionId"],"additionalProperties":false}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is over 1048576 bytes (`too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/connections":{"get":{"operationId":"listConnections","summary":"List your MCP connections","description":"The MCP servers you connected your own account to. Needs a person's token.","tags":["Connections"],"responses":{"200":{"description":"Your connections","content":{"application/json":{"schema":{"type":"object","properties":{"mcp":{"type":"array","items":{"type":"object","properties":{"server":{"type":"string"},"kind":{"enum":["token","oauth"],"description":"A pasted token, or an OAuth sign-in"},"state":{"enum":["connected","needs-reconnect","step-up"],"description":"`needs-reconnect`: the sign-in no longer works; `step-up`: the server asked for more access"},"scope":{"type":"string","description":"The scope the authorization server granted (OAuth)"},"connectedAt":{"type":"integer","description":"Connected (milliseconds since the epoch)"}},"required":["server","kind","state","connectedAt"],"additionalProperties":false}}},"required":["mcp"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/admin/api/people":{"get":{"operationId":"listPeople","summary":"List people and their roles","description":"Needs a role with People & roles.","tags":["People and roles"],"responses":{"200":{"description":"Everyone who can sign in, or could","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Person"}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/admin/api/people/{id}/role":{"put":{"operationId":"setPersonRole","summary":"Give a person a role","description":"Needs People & roles. It applies from their next request, tokens they already hold included. The last enabled Admin keeps Admin (409). From a browser session, send the page's CSRF token as `x-csrf`.","tags":["People and roles"],"parameters":[{"name":"id","in":"path","required":true,"description":"A person's id","schema":{"type":"string"},"example":"0f8fad5b-d9cb-469f-a165-70867728950e"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","description":"A role id"}},"required":["role"],"additionalProperties":false},"example":{"role":"member"}}}},"responses":{"200":{"description":"Changed","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string"}},"required":["id","role"],"additionalProperties":false}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The last admin can't stop being one","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/admin/api/roles":{"get":{"operationId":"listRoles","summary":"List roles, and the permissions a role can hold","description":"Needs People & roles.","tags":["People and roles"],"responses":{"200":{"description":"Every role, and every permission grouped and worded for people","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Role"}},"permissions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"group":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"}},"required":["id","group","label","description"],"additionalProperties":false}}},"required":["items","permissions"],"additionalProperties":false}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createRole","summary":"Make a role","description":"Needs People & roles. Of `mcp.read` and `mcp.full` a role keeps one (full wins). An unknown permission is refused.","tags":["People and roles"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"1 to 40 characters, unique"},"permissions":{"type":"array","items":{"type":"string"}}},"required":["name","permissions"],"additionalProperties":false},"example":{"name":"Auditor","permissions":["admin.usage","admin.audit"]}}}},"responses":{"201":{"description":"Made","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Role"}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A role with that name exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/admin/api/roles/{roleId}":{"patch":{"operationId":"updateRole","summary":"Rename a role or change its permissions","description":"Needs People & roles. Admin can't change; Member keeps its name. Holders get the new permissions on their next request.","tags":["People and roles"],"parameters":[{"name":"roleId","in":"path","required":true,"description":"A role id","schema":{"type":"string"},"example":"member"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"permissions":{"type":"array","items":{"type":"string"}}},"required":[],"additionalProperties":false},"example":{"permissions":["sessions.start","mcp.read"]}}}},"responses":{"200":{"description":"Changed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Role"}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A role with that name exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteRole","summary":"Delete a role","description":"Needs People & roles. Refused while anyone has it or an admission rule gives it (409, naming them); Admin and Member never (400).","tags":["People and roles"],"parameters":[{"name":"roleId","in":"path","required":true,"description":"A role id","schema":{"type":"string"},"example":"auditor"}],"responses":{"204":{"description":"Deleted, or already gone"},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed (`forbidden`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Someone still has it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleInUse"}}}}}}},"/.well-known/oauth-protected-resource/mcp":{"get":{"operationId":"protectedResourceMetadata","summary":"Protected resource metadata for /mcp (RFC 9728)","description":"Names `/mcp` as the resource and this server as its authorization server. Also at `/.well-known/oauth-protected-resource`. No token.","tags":["MCP"],"security":[],"responses":{"200":{"description":"The metadata","content":{"application/json":{"schema":{"type":"object","properties":{"resource":{"type":"string"},"authorization_servers":{"type":"array","items":{"type":"string"}},"scopes_supported":{"type":"array","items":{"type":"string"}},"bearer_methods_supported":{"type":"array","items":{"type":"string"}}},"required":["resource","authorization_servers","scopes_supported","bearer_methods_supported"],"additionalProperties":false}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"operationId":"authorizationServerMetadata","summary":"Authorization server metadata (RFC 8414)","description":"Pistis is the authorization server for `/mcp`: authorization code with PKCE S256, Client ID Metadata Documents and dynamic registration, rotating refresh tokens, revocation. No token.","tags":["MCP"],"security":[],"responses":{"200":{"description":"The metadata","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"required":["issuer","authorization_endpoint","token_endpoint"]}}}}}}},"/oauth/authorize":{"get":{"operationId":"oauthAuthorize","summary":"Begin an authorization (the person's browser)","description":"`response_type=code`, `client_id` (an https metadata document URL, or a registered client), `redirect_uri` (registered), `code_challenge` + `code_challenge_method=S256`, `state`, `scope` (`sessions` or `sessions:read`), `resource` (`<publicUrl>/mcp`). Shows a consent page to the signed-in person; sends the browser back with `code`, `state` and `iss`. A client or redirect it can't accept gets a page, never a redirect.","tags":["MCP"],"security":[],"parameters":[{"name":"client_id","in":"query","schema":{"type":"string"},"example":"https://client.example/mcp-client.json"},{"name":"redirect_uri","in":"query","schema":{"type":"string"},"example":"https://client.example/callback"},{"name":"response_type","in":"query","schema":{"type":"string"},"example":"code"}],"responses":{"200":{"description":"The consent page","content":{"text/html":{"schema":{"type":"string"}}}},"302":{"description":"Back to the client with `code`, `state` and `iss` (or `error`)"},"400":{"description":"A client, redirect or request Pistis won't send the browser on with","content":{"text/html":{"schema":{"type":"string"}}}},"401":{"description":"Sign in first","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/oauth/token":{"post":{"operationId":"oauthToken","summary":"Exchange a code or a refresh token for tokens","description":"`grant_type=authorization_code` (with `code`, `code_verifier`, `client_id`, `redirect_uri`, `resource`) or `grant_type=refresh_token` (with `refresh_token`, `client_id`; the refresh token rotates and a reuse revokes the family). Public clients (`token_endpoint_auth_method: none`).","tags":["MCP"],"security":[],"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","additionalProperties":true},"example":"grant_type=authorization_code&code=x&code_verifier=x&client_id=https%3A%2F%2Fclient.example%2Fmcp-client.json&redirect_uri=https%3A%2F%2Fclient.example%2Fcallback"}}},"responses":{"200":{"description":"Tokens","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthTokens"}}}},"400":{"description":"Refused (`invalid_grant`, `invalid_target`, `unsupported_grant_type`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/oauth/register":{"post":{"operationId":"oauthRegister","summary":"Register a client dynamically (RFC 7591)","description":"A public client with its redirect URIs, good for thirty days of use. Clients with a metadata document need no registration.","tags":["MCP"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_name":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string"}}},"required":["redirect_uris"],"additionalProperties":false},"example":{"client_name":"My MCP client","redirect_uris":["http://localhost:8765/callback"]}}}},"responses":{"201":{"description":"Registered","content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string"},"client_name":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"const":"none"},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}}},"required":["client_id","client_name","redirect_uris","token_endpoint_auth_method","grant_types","response_types"],"additionalProperties":false}}}},"400":{"description":"Refused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"413":{"description":"The body is over 1048576 bytes (`too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/oauth/revoke":{"post":{"operationId":"oauthRevoke","summary":"Revoke an access or refresh token (RFC 7009)","description":"Always 200. A refresh token takes its whole family with it.","tags":["MCP"],"security":[],"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","additionalProperties":true},"example":"token=x"}}},"responses":{"200":{"description":"Revoked, or nothing to revoke"}}}},"/.well-known/mcp-client":{"get":{"operationId":"clientMetadataDocument","summary":"Pistis's OAuth client metadata document","description":"What an MCP server's authorization server fetches when a person connects with OAuth: Pistis's client id (this URL), name and redirect URI (Client ID Metadata Documents). No token.","tags":["Connections"],"security":[],"responses":{"200":{"description":"The document","content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","description":"This document's URL"},"client_name":{"type":"string"},"client_uri":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string"},"application_type":{"type":"string"}},"required":["client_id","client_name","client_uri","redirect_uris","grant_types","response_types","token_endpoint_auth_method","application_type"],"additionalProperties":false}}}}}}},"/connections/mcp/{server}/connect":{"post":{"operationId":"beginMcpConnect","summary":"Begin connecting your account to an MCP server with OAuth","description":"For a server that connects with OAuth. Answers the authorization URL to open in a browser signed in to Pistis as you; the flow expires in ten minutes. A server that takes a pasted token answers 400.","tags":["Connections"],"parameters":[{"name":"server","in":"path","required":true,"description":"A per-person MCP server","schema":{"type":"string"},"example":"linear"}],"responses":{"200":{"description":"Begun","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Where to send the browser"},"expiresAt":{"type":"integer","description":"Until when (milliseconds since the epoch)"}},"required":["url","expiresAt"],"additionalProperties":false}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The server's authorization server could not be used; `error` says why","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/connections/mcp/{server}":{"put":{"operationId":"connectMcp","summary":"Connect your account to an MCP server with a pasted token","description":"For a server that takes a pasted token (one that connects with OAuth answers 400). The token is kept in the secret store and never shown again.","tags":["Connections"],"parameters":[{"name":"server","in":"path","required":true,"description":"A per-person MCP server","schema":{"type":"string"},"example":"linear"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}},"required":["token"],"additionalProperties":false},"example":{"token":"lin_api_…"}}}},"responses":{"200":{"description":"Connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"400":{"description":"Invalid: the body or a parameter is wrong (`invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is over 1048576 bytes (`too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"disconnectMcp","summary":"Disconnect from an MCP server","tags":["Connections"],"parameters":[{"name":"server","in":"path","required":true,"description":"A per-person MCP server","schema":{"type":"string"},"example":"linear"}],"responses":{"200":{"description":"Disconnected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"No valid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such session, or not yours (`unknown_session`); or no such route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/hooks/{key}":{"post":{"operationId":"deliverHook","summary":"Deliver a webhook","description":"Continues every session waiting on `key` (the `wait_for` tool) and starts every flow with `on: { hook: key }`, with the body as the next message. No token: the body is signed with the server's `hookSecret`. GitHub's `x-hub-signature-256` and `x-github-delivery` work as they are.","tags":["Webhooks"],"security":[],"parameters":[{"name":"key","in":"path","required":true,"description":"What the sessions wait on","schema":{"type":"string"},"example":"ci-1234"},{"name":"x-pistis-signature","in":"header","required":true,"description":"`sha256=` and the hex HMAC-SHA256 of the raw body with the secret","schema":{"type":"string"},"example":"sha256=0000"},{"name":"x-pistis-delivery","in":"header","required":true,"description":"Unique per event: a repeat is `duplicate` and does nothing","schema":{"type":"string"},"example":"d-1"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{},"example":{"status":"green"}}}},"responses":{"200":{"description":"Delivered, or a repeat","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"status":{"const":"delivered"},"sessions":{"type":"integer","description":"How many sessions continue"}},"required":["status","sessions"],"additionalProperties":false},{"type":"object","properties":{"status":{"const":"duplicate"}},"required":["status"],"additionalProperties":false}]}}}},"400":{"description":"No delivery id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or wrong signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No session waits on this key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/code-hosts/{connection}/events":{"post":{"operationId":"deliverCodeHostEvent","summary":"Deliver a code host's webhook","description":"Pull request feedback: a review comment, a review that requests changes, a comment that mentions `@pistis`, or a failing check on a pull request a session opened becomes a message in that session, as the person who wrote it and only if they may message it. Point the code host's webhook here (GitHub: the App's webhook URL) with the connection's webhook secret; the code host signs every delivery. Anything not acted on is recorded with why.","tags":["Webhooks"],"security":[],"parameters":[{"name":"connection","in":"path","required":true,"description":"The source control connection's id","schema":{"type":"string"},"example":"github"},{"name":"x-hub-signature-256","in":"header","required":true,"description":"`sha256=` and the hex HMAC-SHA256 of the raw body with the connection's webhook secret","schema":{"type":"string"},"example":"sha256=0000"},{"name":"x-github-delivery","in":"header","required":true,"description":"Unique per delivery: a repeat is `duplicate` and does nothing","schema":{"type":"string"},"example":"d-1"},{"name":"x-github-event","in":"header","required":true,"description":"What happened","schema":{"type":"string"},"example":"pull_request_review_comment"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{},"example":{"action":"created"}}}},"responses":{"200":{"description":"Sent to the session, recorded and not acted on, or a repeat","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"outcome":{"const":"acted"}},"required":["outcome"],"additionalProperties":false},{"type":"object","properties":{"outcome":{"const":"ignored"},"reason":{"type":"string","description":"Why nothing was sent"}},"required":["outcome","reason"],"additionalProperties":false},{"type":"object","properties":{"outcome":{"const":"duplicate"}},"required":["outcome"],"additionalProperties":false}]}}}},"400":{"description":"No delivery id, or a body that isn't JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or wrong signature, or no webhook secret set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No connection here takes events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/healthz":{"get":{"operationId":"health","summary":"Check the server is up","tags":["Server"],"security":[],"responses":{"200":{"description":"Up","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}},"required":["ok"],"additionalProperties":false}}}}}}},"/openapi.json":{"get":{"operationId":"openapi","summary":"This document","tags":["Server"],"security":[],"responses":{"200":{"description":"The OpenAPI document","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"An API token"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string","description":"What went wrong, for people"},"code":{"type":"string","description":"For programs: `unknown_session`, `session_ended`, `forbidden`, `invalid`, `unavailable`, `busy`, `too_large`, or a route's own (`answered`)"}},"required":["error"],"additionalProperties":false},"Ok":{"type":"object","properties":{"ok":{"const":true}},"required":["ok"],"additionalProperties":false},"OAuthError":{"type":"object","properties":{"error":{"type":"string","description":"An OAuth 2.1 error code"},"error_description":{"type":"string"}},"required":["error"],"additionalProperties":false},"OAuthTokens":{"type":"object","properties":{"access_token":{"type":"string"},"token_type":{"const":"Bearer"},"expires_in":{"type":"integer","description":"Seconds"},"refresh_token":{"type":"string","description":"Rotated on each use"},"scope":{"type":"string"}},"required":["access_token","token_type","expires_in","scope"],"additionalProperties":false},"SessionMeta":{"type":"object","description":"Labels fixed at creation: up to 16, key `^[a-z][a-z0-9_]{0,31}$`, value up to 256 characters. `agent` picks an agent, `agent_revision` pins one, `repo` picks repositories (`<connection>:<path>`, comma-separated, up to 10), `pool` picks a pool of your machines. Keys starting with `slack_` or `flow` are Pistis's own and refused.","additionalProperties":{"type":"string","maxLength":256}},"AgentSkill":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"},"description":{"type":"string"},"body":{"type":"string","description":"SKILL.md's body"},"files":{"type":"object","additionalProperties":{"type":"string","description":"base64"}}},"required":["name","version","description","body","files"],"additionalProperties":false},"AgentSpec":{"type":"object","properties":{"instructions":{"type":"string","description":"Added to the system prompt after the host's own"},"model":{"type":"string","description":"`provider/model-id`; one the host can run"},"mcp":{"type":"array","items":{"type":"string","description":"An MCP server by the host's name for it"}},"approvals":{"type":"array","items":{"type":"string","description":"A tool (or `<server>__*`) that waits for approval"}},"skills":{"type":"array","items":{"$ref":"#/components/schemas/AgentSkill"}}},"required":[],"additionalProperties":false},"ThinkingLevel":{"type":"string","enum":["off","minimal","low","medium","high","xhigh","max"]},"SessionModel":{"type":"object","properties":{"id":{"type":"string","description":"`provider/model-id`"},"thinking":{"$ref":"#/components/schemas/ThinkingLevel"}},"required":["id","thinking"],"additionalProperties":false},"ModelInfo":{"type":"object","properties":{"id":{"type":"string","description":"`provider/model-id`"},"name":{"type":"string"},"contextWindow":{"type":["integer","null"],"description":"Tokens; null when unknown"},"thinking":{"type":"array","items":{"$ref":"#/components/schemas/ThinkingLevel"}},"cost":{"oneOf":[{"type":"object","properties":{"input":{"type":"number","description":"Dollars per million tokens"},"output":{"type":"number","description":"Dollars per million tokens"}},"required":["input","output"],"additionalProperties":false},{"type":"null"}]}},"required":["id","name","contextWindow","thinking","cost"],"additionalProperties":false},"SessionInfo":{"type":"object","properties":{"sessionId":{"type":"string"},"requestId":{"type":"string","description":"The caller's key, as given"},"principal":{"type":"string","description":"Whose session it is"},"meta":{"$ref":"#/components/schemas/SessionMeta"},"skills":{"type":"object","additionalProperties":{"type":"string","description":"Skill version pinned at creation"}},"createdAt":{"type":"integer","description":"Created (milliseconds since the epoch)"},"endedAt":{"type":"integer","description":"Ended: sandbox deleted, input refused, conversation kept (milliseconds since the epoch)"},"model":{"$ref":"#/components/schemas/SessionModel"},"parent":{"oneOf":[{"type":"object","properties":{"kind":{"const":"branch"},"sessionId":{"type":"string"},"atSeq":{"type":"integer","description":"The last entry kept"}},"required":["kind","sessionId","atSeq"],"additionalProperties":false},{"type":"object","properties":{"kind":{"const":"subagent"},"sessionId":{"type":"string"},"toolCallId":{"type":"string"},"task":{"type":"string"}},"required":["kind","sessionId","toolCallId","task"],"additionalProperties":false},{"type":"object","properties":{"kind":{"const":"flow"},"sessionId":{"type":"string","description":"The run's own session"},"runId":{"type":"string"},"key":{"type":"string"}},"required":["kind","sessionId","runId","key"],"additionalProperties":false}]}},"required":["sessionId","requestId","principal","meta","skills","createdAt","model"],"additionalProperties":false},"Attachment":{"type":"object","properties":{"attachmentId":{"type":"string","description":"`att_<hex>`"},"name":{"type":"string","description":"Unique in the session; the sandbox has it at `/workspace/.pistis/attachments/<name>`"},"size":{"type":"integer","description":"Bytes"},"type":{"type":"string","description":"Media type"}},"required":["attachmentId","name","size","type"],"additionalProperties":false},"Usage":{"type":"object","properties":{"input":{"type":"integer","description":"Input tokens"},"output":{"type":"integer","description":"Output tokens"},"cacheRead":{"type":"integer"},"cacheWrite":{"type":"integer"},"totalTokens":{"type":"integer"},"cost":{"type":"number","description":"Dollars; 0 when the provider reports none"}},"required":["input","output","cacheRead","cacheWrite","totalTokens","cost"],"additionalProperties":false},"SessionUsage":{"type":"object","properties":{"input":{"type":"integer","description":"Input tokens"},"output":{"type":"integer","description":"Output tokens"},"cacheRead":{"type":"integer"},"cacheWrite":{"type":"integer"},"totalTokens":{"type":"integer"},"cost":{"type":"number","description":"Dollars; 0 when the provider reports none"},"byModel":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/Usage"}}},"required":["input","output","cacheRead","cacheWrite","totalTokens","cost","byModel"],"additionalProperties":false},"InputMode":{"type":"string","enum":["agent","plan","auto"],"description":"`agent` runs tools and gated ones wait for a person; `plan` refuses every tool that could change something; `auto` approves gated tools as they are called, by the sender (where the server allows it)"},"ParkedStep":{"type":"object","properties":{"id":{"type":"string","description":"The step's task"},"toolCallId":{"type":"string","description":"The tool call it is, when it is one"}},"required":["id"],"additionalProperties":false},"PendingItem":{"type":"object","properties":{"submissionId":{"type":"string"},"mode":{"type":"string","enum":["steer","followUp"]},"text":{"type":"string"},"at":{"type":"integer","description":"Sent (milliseconds since the epoch)"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false}},"required":["submissionId","mode","text","at"],"additionalProperties":false},"ToolImage":{"type":"object","properties":{"mimeType":{"type":"string","description":"image/jpeg, image/png, …"},"data":{"type":"string","description":"The image's bytes, base64"}},"required":["mimeType","data"],"additionalProperties":false},"NestedCall":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string","enum":["ok","error","unfinished"]},"durationMs":{"type":"integer"},"args":{"type":"string","description":"Compact JSON, cut for display"},"error":{"type":"string"}},"required":["name","status"],"additionalProperties":false},"ToolCallView":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"arguments":{}},"required":["id","name","arguments"],"additionalProperties":false},"TranscriptEntry":{"oneOf":[{"type":"object","properties":{"seq":{"type":"integer","description":"1-based ordinal of the entry in the session"},"at":{"type":"integer","description":"When its message was made; absent for bookkeeping entries (milliseconds since the epoch)"},"kind":{"const":"user"},"text":{"type":"string"},"mode":{"$ref":"#/components/schemas/InputMode"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Attachment"}}},"required":["seq","kind","text","mode","attachments"],"additionalProperties":false},{"type":"object","properties":{"seq":{"type":"integer","description":"1-based ordinal of the entry in the session"},"at":{"type":"integer","description":"When its message was made; absent for bookkeeping entries (milliseconds since the epoch)"},"kind":{"const":"assistant"},"text":{"type":"string"},"toolCalls":{"type":"array","items":{"$ref":"#/components/schemas/ToolCallView"}},"error":{"type":"string","description":"The model call failed with this message; the turn ended unanswered (`settled` says `model_error`)"},"model":{"type":"string","description":"Present on measured entries, with `durationMs`, `usage` and `contextWindow`"},"durationMs":{"type":"integer"},"usage":{"$ref":"#/components/schemas/Usage"},"contextWindow":{"type":["integer","null"]}},"required":["seq","kind","text"],"additionalProperties":false},{"type":"object","properties":{"seq":{"type":"integer","description":"1-based ordinal of the entry in the session"},"at":{"type":"integer","description":"When its message was made; absent for bookkeeping entries (milliseconds since the epoch)"},"kind":{"const":"tool-result"},"toolCallId":{"type":"string"},"toolName":{"type":"string"},"isError":{"type":"boolean"},"text":{"type":"string"},"durationMs":{"type":"integer","description":"Absent for a call that never ran"},"nested":{"type":"array","items":{"$ref":"#/components/schemas/NestedCall"}},"images":{"type":"array","items":{"$ref":"#/components/schemas/ToolImage"}}},"required":["seq","kind","toolCallId","toolName","isError","text"],"additionalProperties":false},{"type":"object","properties":{"seq":{"type":"integer","description":"1-based ordinal of the entry in the session"},"at":{"type":"integer","description":"When its message was made; absent for bookkeeping entries (milliseconds since the epoch)"},"kind":{"const":"system"},"text":{"type":"string"}},"required":["seq","kind","text"],"additionalProperties":false},{"type":"object","properties":{"seq":{"type":"integer","description":"1-based ordinal of the entry in the session"},"at":{"type":"integer","description":"When its message was made; absent for bookkeeping entries (milliseconds since the epoch)"},"kind":{"const":"brief"},"from":{"type":"string","description":"The parent session"},"task":{"type":"string"}},"required":["seq","kind","from","task"],"additionalProperties":false},{"type":"object","properties":{"seq":{"type":"integer","description":"1-based ordinal of the entry in the session"},"at":{"type":"integer","description":"When its message was made; absent for bookkeeping entries (milliseconds since the epoch)"},"kind":{"const":"retry"},"toolCallId":{"type":"string"},"toolName":{"type":"string"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false}},"required":["seq","kind","toolCallId","toolName"],"additionalProperties":false},{"type":"object","properties":{"seq":{"type":"integer","description":"1-based ordinal of the entry in the session"},"at":{"type":"integer","description":"When its message was made; absent for bookkeeping entries (milliseconds since the epoch)"},"kind":{"const":"model"},"model":{"type":"string"},"thinking":{"$ref":"#/components/schemas/ThinkingLevel"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false}},"required":["seq","kind","model","thinking"],"additionalProperties":false},{"type":"object","properties":{"seq":{"type":"integer","description":"1-based ordinal of the entry in the session"},"at":{"type":"integer","description":"When its message was made; absent for bookkeeping entries (milliseconds since the epoch)"},"kind":{"const":"takeover"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false},"since":{"type":"integer","description":"Took over (milliseconds since the epoch)"},"durationMs":{"type":"integer","description":"How long they had the screen"},"how":{"type":"string","enum":["handback","timeout"]},"note":{"type":"string","description":"Their note to the agent"}},"required":["seq","kind","since","durationMs","how"],"additionalProperties":false},{"type":"object","properties":{"seq":{"type":"integer","description":"1-based ordinal of the entry in the session"},"at":{"type":"integer","description":"When its message was made; absent for bookkeeping entries (milliseconds since the epoch)"},"kind":{"const":"pause"},"paused":{"type":"boolean"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false}},"required":["seq","kind","paused"],"additionalProperties":false},{"type":"object","properties":{"seq":{"type":"integer","description":"1-based ordinal of the entry in the session"},"at":{"type":"integer","description":"When its message was made; absent for bookkeeping entries (milliseconds since the epoch)"},"kind":{"const":"title"},"title":{"type":"string","description":"The session's name now"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false}},"required":["seq","kind","title"],"additionalProperties":false},{"type":"object","properties":{"seq":{"type":"integer","description":"1-based ordinal of the entry in the session"},"at":{"type":"integer","description":"When its message was made; absent for bookkeeping entries (milliseconds since the epoch)"},"kind":{"const":"parked-retry"},"steps":{"type":"integer","description":"Steps run again"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false}},"required":["seq","kind","steps"],"additionalProperties":false},{"type":"object","properties":{"seq":{"type":"integer","description":"1-based ordinal of the entry in the session"},"at":{"type":"integer","description":"When its message was made; absent for bookkeeping entries (milliseconds since the epoch)"},"kind":{"const":"withdrawn"},"submissionId":{"type":"string"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false}},"required":["seq","kind","submissionId"],"additionalProperties":false},{"type":"object","properties":{"seq":{"type":"integer","description":"1-based ordinal of the entry in the session"},"at":{"type":"integer","description":"When its message was made; absent for bookkeeping entries (milliseconds since the epoch)"},"kind":{"const":"other"},"text":{"type":"string"}},"required":["seq","kind","text"],"additionalProperties":false}]},"Activity":{"oneOf":[{"type":"object","properties":{"doing":{"const":"thinking"}},"required":["doing"],"additionalProperties":false},{"type":"object","properties":{"doing":{"const":"tool"},"toolCallId":{"type":"string"},"name":{"type":"string"},"startedAt":{"type":"integer","description":"Asked for (milliseconds since the epoch)"}},"required":["doing","toolCallId","name","startedAt"],"additionalProperties":false},{"type":"object","properties":{"doing":{"const":"compacting"}},"required":["doing"],"additionalProperties":false},{"type":"object","properties":{"doing":{"const":"backing-off"},"until":{"type":"integer","description":"Tried again at (milliseconds since the epoch)"},"error":{"type":"string"}},"required":["doing","until","error"],"additionalProperties":false}]},"SessionStatus":{"oneOf":[{"type":"object","properties":{"state":{"const":"idle"}},"required":["state"],"additionalProperties":false},{"type":"object","properties":{"state":{"const":"working"},"since":{"type":"integer","description":"Since (milliseconds since the epoch)"},"activity":{"$ref":"#/components/schemas/Activity"}},"required":["state","since","activity"],"additionalProperties":false},{"type":"object","properties":{"state":{"const":"waiting"},"since":{"type":"integer","description":"Since (milliseconds since the epoch)"},"approvals":{"type":"array","items":{"type":"string","description":"An approval key"}},"asks":{"type":"array","items":{"type":"string","description":"An ask id"}}},"required":["state","since","approvals","asks"],"additionalProperties":false},{"type":"object","properties":{"state":{"const":"parked"},"since":{"type":"integer","description":"Known stopped since (milliseconds since the epoch)"},"steps":{"type":"integer","description":"Steps stopped after repeated crashes; they run again only when someone retries them"}},"required":["state","since","steps"],"additionalProperties":false},{"type":"object","properties":{"state":{"const":"paused"},"since":{"type":"integer","description":"Paused (milliseconds since the epoch)"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false}},"required":["state","since","by"],"additionalProperties":false},{"type":"object","properties":{"state":{"const":"ended"},"at":{"type":"integer","description":"Ended (milliseconds since the epoch)"}},"required":["state","at"],"additionalProperties":false}]},"Decision":{"oneOf":[{"type":"object","properties":{"kind":{"const":"approval"},"at":{"type":"integer","description":"Decided (milliseconds since the epoch)"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false},"seq":{"type":"integer","description":"The timeline entry it belongs to"},"approved":{"type":"boolean"},"auto":{"const":true},"tool":{"type":"string"},"args":{"type":"string","description":"The call's arguments as JSON (the command, the diff), cut for display"},"toolCallId":{"type":"string"}},"required":["kind","at","approved","tool","args"],"additionalProperties":false},{"type":"object","properties":{"kind":{"const":"answer"},"at":{"type":"integer","description":"Decided (milliseconds since the epoch)"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false},"seq":{"type":"integer","description":"The timeline entry it belongs to"},"question":{"type":"string"},"answer":{"type":"string"}},"required":["kind","at","question","answer"],"additionalProperties":false},{"type":"object","properties":{"kind":{"const":"takeover"},"at":{"type":"integer","description":"Decided (milliseconds since the epoch)"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false},"seq":{"type":"integer","description":"The timeline entry it belongs to"},"durationMs":{"type":"integer","description":"How long they had the screen"},"how":{"type":"string","enum":["handback","timeout"]},"note":{"type":"string","description":"Their note to the agent"}},"required":["kind","at","durationMs","how"],"additionalProperties":false},{"type":"object","properties":{"kind":{"const":"annotation"},"at":{"type":"integer","description":"Decided (milliseconds since the epoch)"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false},"seq":{"type":"integer","description":"The timeline entry it belongs to"},"note":{"type":"string"},"page":{"type":"string","description":"The page marked"},"attachmentId":{"type":"string","description":"The crop"}},"required":["kind","at","note","page"],"additionalProperties":false},{"type":"object","properties":{"kind":{"const":"parked-retry"},"at":{"type":"integer","description":"Decided (milliseconds since the epoch)"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false},"seq":{"type":"integer","description":"The timeline entry it belongs to"},"steps":{"type":"integer"}},"required":["kind","at","steps"],"additionalProperties":false},{"type":"object","properties":{"kind":{"const":"pause"},"at":{"type":"integer","description":"Decided (milliseconds since the epoch)"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false},"seq":{"type":"integer","description":"The timeline entry it belongs to"},"paused":{"type":"boolean"}},"required":["kind","at","paused"],"additionalProperties":false}]},"PauseState":{"oneOf":[{"type":"object","properties":{"paused":{"const":false}},"required":["paused"],"additionalProperties":false},{"type":"object","properties":{"paused":{"const":true},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false},"since":{"type":"integer","description":"Paused (milliseconds since the epoch)"}},"required":["paused","by","since"],"additionalProperties":false}]},"ApprovalEvent":{"type":"object","properties":{"kind":{"const":"approval"},"key":{"type":"string"},"tool":{"type":"string"},"args":{"type":"string","description":"Arguments as JSON, cut for display"},"requestedAt":{"type":"integer","description":"Asked (milliseconds since the epoch)"},"decided":{"type":"object","properties":{"approved":{"type":"boolean"},"by":{"type":"string","description":"A principal"},"at":{"type":"integer","description":"Decided (milliseconds since the epoch)"},"auto":{"const":true}},"required":["approved","by","at"],"additionalProperties":false}},"required":["kind","key","tool","args","requestedAt"],"additionalProperties":false},"Ask":{"type":"object","properties":{"askId":{"type":"string"},"question":{"type":"string"},"options":{"type":"array","items":{"type":"string"}},"at":{"type":"integer","description":"Asked (milliseconds since the epoch)"}},"required":["askId","question","at"],"additionalProperties":false},"AskEvent":{"type":"object","properties":{"kind":{"const":"ask"},"ask":{"$ref":"#/components/schemas/Ask"},"answered":{"type":"object","properties":{"answer":{"type":"string"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false},"at":{"type":"integer","description":"Answered (milliseconds since the epoch)"}},"required":["answer","by","at"],"additionalProperties":false}},"required":["kind","ask"],"additionalProperties":false},"Child":{"type":"object","properties":{"sessionId":{"type":"string"},"task":{"type":"string"},"status":{"$ref":"#/components/schemas/SessionStatus"}},"required":["sessionId","task","status"],"additionalProperties":false},"SessionEvent":{"oneOf":[{"$ref":"#/components/schemas/TranscriptEntry"},{"$ref":"#/components/schemas/ApprovalEvent"},{"$ref":"#/components/schemas/AskEvent"},{"type":"object","properties":{"kind":{"const":"pending"},"items":{"type":"array","items":{"$ref":"#/components/schemas/PendingItem"}}},"required":["kind","items"],"additionalProperties":false},{"type":"object","properties":{"kind":{"const":"status"},"status":{"$ref":"#/components/schemas/SessionStatus"}},"required":["kind","status"],"additionalProperties":false},{"type":"object","properties":{"kind":{"const":"usage"},"usage":{"$ref":"#/components/schemas/SessionUsage"}},"required":["kind","usage"],"additionalProperties":false},{"$ref":"#/components/schemas/ReplyEvent"}]},"ReplyEvent":{"type":"object","properties":{"kind":{"const":"reply"},"id":{"type":"string","description":"One in-progress reply"},"offset":{"type":"integer","description":"Where `text` goes in the reply's text so far; 0 carries the whole text so far"},"text":{"type":"string","description":"The reply's text from `offset`; empty at offset 0: no reply is in progress any more"}},"required":["kind","id","offset","text"],"additionalProperties":false},"Settled":{"oneOf":[{"type":"object","properties":{"status":{"const":"done"}},"required":["status"],"additionalProperties":false},{"type":"object","properties":{"status":{"const":"unanswered"},"reason":{"type":"string"}},"required":["status","reason"],"additionalProperties":false}]},"ScreenControl":{"oneOf":[{"type":"object","properties":{"holder":{"const":"agent"}},"required":["holder"],"additionalProperties":false},{"type":"object","properties":{"holder":{"const":"person"},"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false},"since":{"type":"integer","description":"Took over (milliseconds since the epoch)"},"until":{"type":"integer","description":"Comes back to the agent unless renewed (milliseconds since the epoch)"}},"required":["holder","by","since","until"],"additionalProperties":false}]},"ScreenInput":{"oneOf":[{"type":"object","properties":{"type":{"const":"mouse"},"action":{"type":"string","enum":["move","down","up"]},"x":{"type":"number","description":"In the picture's pixels"},"y":{"type":"number"},"button":{"type":"string","enum":["left","right"]}},"required":["type","action","x","y"],"additionalProperties":false},{"type":"object","properties":{"type":{"const":"wheel"},"x":{"type":"number"},"y":{"type":"number"},"dx":{"type":"number"},"dy":{"type":"number"}},"required":["type","x","y","dx","dy"],"additionalProperties":false},{"type":"object","properties":{"type":{"const":"key"},"action":{"type":"string","enum":["down","up"]},"key":{"type":"string","description":"As `KeyboardEvent.key`"},"code":{"type":"string"},"text":{"type":"string","description":"The character it types"},"keyCode":{"type":"integer"}},"required":["type","action","key"],"additionalProperties":false},{"type":"object","properties":{"type":{"const":"text"},"text":{"type":"string","description":"Pasted text"}},"required":["type","text"],"additionalProperties":false}]},"SandboxStatus":{"oneOf":[{"type":"object","properties":{"generation":{"type":"integer","description":"Counts sandboxes this session had"},"state":{"const":"missing"}},"required":["generation","state"],"additionalProperties":false},{"type":"object","properties":{"generation":{"type":"integer"},"state":{"type":"string","enum":["running","paused","stopped"]},"id":{"type":"string"}},"required":["generation","state","id"],"additionalProperties":false}]},"FlowTrigger":{"oneOf":[{"type":"object","properties":{"manual":{"const":true}},"required":["manual"],"additionalProperties":false},{"type":"object","properties":{"hook":{"type":"string","description":"Runs on each signed `POST /hooks/<hook>`"}},"required":["hook"],"additionalProperties":false},{"type":"object","properties":{"every":{"type":"string","description":"A schedule: `30m`, `6h`, `1d`"}},"required":["every"],"additionalProperties":false},{"type":"object","properties":{"at":{"type":"string","description":"A time of day in UTC, `HH:MM`"},"days":{"type":"array","items":{"type":"string","enum":["mon","tue","wed","thu","fri","sat","sun"],"description":"The days it runs on; every day without"}}},"required":["at"],"additionalProperties":false}]},"FlowSpec":{"type":"object","properties":{"id":{"type":"string","description":"`^[a-z0-9][a-z0-9-]{0,63}$`"},"on":{"$ref":"#/components/schemas/FlowTrigger"},"steps":{"type":"array","items":{"type":"string","description":"One message per step, sent in order"}},"repos":{"type":"array","items":{"type":"string","description":"`<connection>:<path>`; the steps run once in each, side by side"}},"concurrency":{"type":"integer","minimum":1,"maximum":32,"description":"With repos: how many at once (default 4)"}},"required":["id","on","steps"],"additionalProperties":false},"FlowSummary":{"type":"object","properties":{"id":{"type":"string"},"on":{"$ref":"#/components/schemas/FlowTrigger"},"built":{"$ref":"#/components/schemas/FlowSpec"},"saved":{"type":"object","properties":{"by":{"type":"object","properties":{"principal":{"type":"string","description":"The person's principal"},"name":{"type":"string"}},"required":["principal","name"],"additionalProperties":false},"at":{"type":"integer","description":"Saved (milliseconds since the epoch)"}},"required":["by","at"],"additionalProperties":false}},"required":["id","on"],"additionalProperties":false},"FlowRun":{"type":"object","properties":{"runId":{"type":"string"},"flowId":{"type":"string"},"sessionId":{"type":"string","description":"The run's own session"},"status":{"type":"string","enum":["running","done","failed","stopped"]},"startedAt":{"type":"integer","description":"Started (milliseconds since the epoch)"},"children":{"type":"object","additionalProperties":{"oneOf":[{"type":"object","properties":{"state":{"const":"running"},"sessionId":{"type":"string"}},"required":["state","sessionId"],"additionalProperties":false},{"type":"object","properties":{"state":{"const":"done"},"sessionId":{"type":"string"}},"required":["state","sessionId"],"additionalProperties":false},{"type":"object","properties":{"state":{"const":"failed"},"sessionId":{"type":"string"},"reason":{"type":"string"}},"required":["state","reason"],"additionalProperties":false},{"type":"object","properties":{"state":{"const":"stopped"},"sessionId":{"type":"string"}},"required":["state"],"additionalProperties":false}]}}},"required":["runId","flowId","sessionId","status","startedAt","children"],"additionalProperties":false},"RepoChoice":{"type":"object","properties":{"repo":{"type":"string","description":"What `meta.repo` takes: `<connection>:<path>`"},"connection":{"type":"string"},"path":{"type":"string"},"label":{"type":"string","description":"The connection, as people know it"},"defaultBranch":{"type":"string"},"private":{"type":"boolean"},"webUrl":{"type":"string"}},"required":["repo","connection","path","label","defaultBranch","private","webUrl"],"additionalProperties":false},"ShareRole":{"type":"string","enum":["viewer","collaborator","approver"]},"Grant":{"type":"object","properties":{"principal":{"type":"string"},"role":{"$ref":"#/components/schemas/ShareRole"},"grantedBy":{"type":"string"},"grantedAt":{"type":"integer","description":"Granted (milliseconds since the epoch)"}},"required":["principal","role","grantedBy","grantedAt"],"additionalProperties":false},"ShareLink":{"type":"object","properties":{"linkId":{"type":"string"},"role":{"const":"viewer"},"expiresAt":{"type":"integer","description":"Expires (milliseconds since the epoch)"}},"required":["linkId","role","expiresAt"],"additionalProperties":false},"Role":{"type":"object","properties":{"id":{"type":"string","description":"`admin` and `member` are built in; others are made by an admin"},"name":{"type":"string"},"builtIn":{"type":"boolean"},"permissions":{"type":"array","items":{"type":"string","description":"A permission id from `GET /admin/api/roles`"}},"people":{"type":"integer","description":"How many people have it"}},"required":["id","name","builtIn","permissions","people"],"additionalProperties":false},"Person":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"role":{"type":"string","description":"Their role's id"},"disabled":{"type":"boolean"}},"required":["id","name","role","disabled"],"additionalProperties":false},"RoleInUse":{"type":"object","properties":{"error":{"type":"string","description":"What went wrong, for people"},"holders":{"type":"array","items":{"type":"string","description":"A person, or an admission rule (`@domain`)"}}},"required":["error"],"additionalProperties":false}}}}