{"openapi":"3.1.0","info":{"title":"AgentSky developer API","version":"1","description":"Long-lived agents over HTTP: /v1 management plus a streaming conversation plane. Auth: `Authorization: Bearer ast_…` (Developer → API keys or `sky auth login`). Scopes: read ⊂ write ⊂ admin. Rate limit: 100,000 requests/min per token (429 + Retry-After). Human docs: https://platform.agentsky.dev/docs"},"servers":[{"url":"https://api.agentsky.dev/v1"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"ast_ token"}},"schemas":{"WorkspaceConnections":{"type":"object","required":["sharing","connections"],"properties":{"sharing":{"type":"boolean","description":"Whether members can share connected apps with this workspace."},"can_connect":{"type":"boolean","description":"While sharing is on: whether the caller may connect an app for the workspace itself."},"connections":{"type":"array","items":{"type":"object","properties":{"connection_id":{"type":"string"},"app":{"type":"string"},"app_name":{"type":"string"},"label":{"type":"string"},"shared_by":{"type":"object","properties":{"user_id":{"type":"string"},"name":{"type":"string","nullable":true}}},"shared_at":{"type":"string","format":"date-time"},"mine":{"type":"boolean","description":"True when the caller is the person who shared it."},"workspace_owned":{"type":"boolean","description":"Present and true when the workspace itself owns the connection."}}}}}},"WorkspaceKey":{"type":"object","required":["id","name","prefix","scopes","created_by","created_at"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"prefix":{"type":"string","description":"The start of the secret, to tell one key from another."},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","admin"]}},"created_by":{"type":"object","properties":{"user_id":{"type":"string"},"name":{"type":"string","nullable":true}}},"created_at":{"type":"string","format":"date-time"},"last_used_at":{"type":"string","format":"date-time","nullable":true},"expires_at":{"type":"string","format":"date-time","nullable":true},"revoked_at":{"type":"string","format":"date-time","nullable":true}}},"SessionShareLink":{"type":"object","required":["token"],"description":"token is null when sharing is off. A guest link carries shareUrl; a view-only link does not.","properties":{"token":{"type":"string","nullable":true},"access":{"type":"string","enum":["prompt","view"]},"shareUrl":{"type":"string"}}},"SessionAccess":{"type":"object","required":["session_id","title","agent_type","llm","visibility","access","owner","workspace","viewers"],"properties":{"session_id":{"type":"string"},"title":{"type":"string","nullable":true},"agent_type":{"type":"string"},"llm":{"type":"string"},"visibility":{"type":"string","enum":["workspace","private"]},"access":{"type":"string","enum":["owner","member","viewer"]},"owner":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true}}},"workspace":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"personal":{"type":"boolean"}}},"viewers":{"type":"array","nullable":true,"items":{"type":"object","properties":{"email":{"type":"string"},"added_at":{"type":"string","format":"date-time"}}}}}},"MessagePart":{"$schema":"http://json-schema.org/draft-07/schema#","oneOf":[{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"text"},"text":{"default":"","type":"string"},"stream_id":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"stream_index":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]}},"required":["index","type"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"reasoning"},"text":{"default":"","type":"string"},"redacted":{"default":false,"type":"boolean"},"stream_id":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"stream_index":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]}},"required":["index","type"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"tool_call"},"call_id":{"type":"string"},"tool_name":{"type":"string"},"args":{"default":{},"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"args_partial":{"type":["string","null"]}},"required":["index","type","call_id","tool_name"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"tool_result"},"call_id":{"type":"string"},"tool_name":{"type":"string"},"status":{"default":"ok","type":"string","enum":["ok","error"]},"result":{"default":{},"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["index","type","call_id","tool_name"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"file"},"name":{"type":"string"},"media_type":{"type":"string"},"uri":{"type":["string","null"]},"data":{"type":["string","null"]},"size_bytes":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]}},"required":["index","type","name","media_type"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"image"},"media_type":{"type":"string"},"uri":{"type":["string","null"]},"data":{"type":["string","null"]},"alt":{"type":["string","null"]},"width":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]}},"required":["index","type","media_type"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"video"},"media_type":{"type":"string"},"uri":{"type":["string","null"]},"data":{"type":["string","null"]},"alt":{"type":["string","null"]},"width":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"duration_ms":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"size_bytes":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"thumbnail_uri":{"type":["string","null"]}},"required":["index","type","media_type"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"status"},"level":{"type":"string","enum":["thinking","working","waiting","idle","done"]},"text":{"type":["string","null"]}},"required":["index","type","level"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"error"},"code":{"type":"string"},"message":{"type":"string"},"retryable":{"default":false,"type":"boolean"}},"required":["index","type","code","message"]}]},"CreateAgent":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"name":{"description":"Prompt label only — not an address. An agent is addressed by the `id` in the response (agent_…); names are free and need not be unique","type":"string","maxLength":60},"description":{"type":"string","maxLength":500},"agentType":{"type":"string","enum":["hermes","claude_code","codex","openclaw","pi","dsh","kimi_code","opencode","jev","agoragentic_acp","amp_acp","auggie","autohand","cline","codebuddy_code","cortex_code","corust_agent","crow_cli","cursor","deepagents","devin","dimcode","dirac","factory_droid","fast_agent","gemini","github_copilot_cli","glm_acp_agent","antigravity_acp","goose","grok_build","harn","junie","kilo","kimchi","minimax_code","minion_code","mistral_vibe","nova","poolside","qoder","qwen_code","sigit","stakpak","vtcode","code_assistant","docker_cagent","kiro","openhands","muse_code","workspace_acp"]},"llm":{"type":"string"},"reasoningEffort":{"description":"Harness/model-compatible reasoning effort; omitted = model-compatible fallback for constrained models, otherwise harness default. Explicit values must fit both agentType and llm — agoragentic_acp: not supported; amp_acp: not supported; auggie: not supported; autohand: not supported; cline: not supported; codebuddy_code: not supported; cortex_code: not supported; corust_agent: not supported; crow_cli: not supported; cursor: not supported; deepagents: not supported; devin: not supported; dimcode: not supported; dirac: not supported; factory_droid: not supported; fast_agent: not supported; gemini: not supported; github_copilot_cli: not supported; glm_acp_agent: not supported; antigravity_acp: not supported; goose: not supported; grok_build: not supported; harn: not supported; junie: not supported; kilo: not supported; kimchi: not supported; minimax_code: not supported; minion_code: not supported; mistral_vibe: not supported; nova: not supported; poolside: not supported; qoder: not supported; qwen_code: not supported; sigit: not supported; stakpak: not supported; vtcode: not supported; code_assistant: not supported; docker_cagent: not supported; kiro: not supported; muse_code: not supported; openhands: not supported; hermes: none/minimal/low/medium/high/xhigh/max/ultra; claude_code: low/medium/high/xhigh/max; codex: none/minimal/low/medium/high/xhigh/max; openclaw: not supported; jev: not supported; pi: off/minimal/low/medium/high/xhigh/max; dsh: not supported; kimi_code: not supported; opencode: none/minimal/low/medium/high/xhigh/max; workspace_acp: not supported; models: claude-haiku-4-5: not supported; gemini-3.8-flash: low/medium/high; gemini-3.5-flash: low/medium/high; glm-5.3: low/high/max; glm-5.3-flash: low/high/max; grok-4.6: low/medium/high; grok-4.7: low/medium/high/xhigh; codex/hermes + gpt-6.1-sol: low/medium/high/xhigh/max","type":"string","enum":["none","off","minimal","low","medium","high","xhigh","max","ultra"]},"prompt":{"type":"string","maxLength":100000},"displayName":{"description":"What the agent is called in the console and in channels; omitted = an auto-generated asteroid name","type":"string","maxLength":60},"capabilities":{"type":"array","items":{"type":"string","enum":["embedding.openai","embedding.voyage","rerank.voyage","ocr.mistral","exa.search","exa.contents","tinyfish.fetch","tinyfish.browser","tinyfish.agent","dataforseo.serp","dataforseo.ai-keywords","dataforseo.llm-responses","dataforseo.app-info","dataforseo.app-search","dataforseo.backlinks","dataforseo.business-reviews","dataforseo.business-pinterest","dataforseo.content-analysis","dataforseo.technologies","dataforseo.keyword-data","dataforseo.labs","dataforseo.amazon","dataforseo.onpage","gptimage.generate","rembg.remove-background","seedance.generate","mm.i2v","wan.t2v","wan.i2v","happyhorse.t2v","minimax.h3","fish-audio.transcribe","code-review","exa.answer","googlemap.geocode","googlemap.places","agentmail.list-inboxes","tinyfish.search","tinyfish.profile-list","meta.transcribe","minimax.tts","elevenlabs.sound","zai.transcribe","openai.transcribe","fish-audio.tts","google.image","openai.image-2.5","wan.image","logo.lookup","openmeteo.weather","frankfurter.fx","dictionary.define","openlibrary.search","googledns.resolve","qrserver.create","social-boost.catalog"]}},"instructions":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"pattern":".*\\.md$"},"content":{"default":"","type":"string"}},"required":["name"]}},"skills":{"description":"RFC-0073 skill attachments: store references ({type:'skill', skillId, version?: 'latest'|skr_…}) and GitHub shortcuts ({type:'github', url, ref?, tokenSecretRef?}). Max 20.","type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"skill"},"skillId":{"type":"string","minLength":1},"version":{"default":"latest","type":"string","minLength":1}},"required":["type","skillId"]},{"type":"object","properties":{"type":{"type":"string","const":"github"},"url":{"type":"string","format":"uri"},"ref":{"description":"Branch or commit SHA; default branch when omitted.","type":"string","minLength":1},"tokenSecretRef":{"description":"Agent secret key holding a clone token for private repos.","type":"string","minLength":1}},"required":["type","url"]}]}},"mcpServers":{"description":"Remote streamable-HTTP MCP servers this agent connects to.","maxItems":20,"type":"array","items":{"type":"object","properties":{"type":{"default":"url","type":"string","const":"url"},"name":{"type":"string","minLength":1,"maxLength":255},"url":{"type":"string","format":"uri"},"tools":{"type":"object","properties":{"include":{"default":[],"maxItems":200,"type":"array","items":{"type":"string","minLength":1}},"exclude":{"default":[],"maxItems":200,"type":"array","items":{"type":"string","minLength":1}}}}},"required":["name","url"]}},"hooks":{"description":"Shell commands run in the session's pod at lifecycle events ({event, command, matcher?, timeout_s?}). Every harness accepts every event; a hook can stop a prompt or a tool call only on a harness whose own hook system fires that event. Max 20.","maxItems":20,"type":"array","items":{"type":"object","properties":{"event":{"type":"string","enum":["pre_session_start","session_start","user_prompt_submit","pre_tool_use","post_tool_use","stop","session_end"]},"command":{"type":"string","minLength":1,"maxLength":4000},"matcher":{"type":"string","minLength":1,"maxLength":255},"timeout_s":{"type":"integer","minimum":1,"maximum":600}},"required":["event","command"],"additionalProperties":false}},"customData":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"name":{"type":"string","pattern":"^[a-z0-9_]+$"},"kind":{"type":"string","enum":["spreadsheet","doc","private_api","other"]},"scope":{"default":"creator","type":"string","enum":["creator","user"]},"description":{"type":"string"},"uri":{"type":"string"},"config":{"default":{},"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["id","name","kind"]}},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"environmentId":{"description":"The workspace environment a session of this agent boots in when its create names no `environment_id`; ahead of the workspace default. Omitted = no agent default.","type":"string","minLength":1},"vaultId":{"description":"A workspace vault every session of this agent carries: after the vaults the session create names, ahead of the workspace default. Omitted = no agent vault.","type":"string","minLength":1},"capabilityPolicies":{"type":"object","propertyNames":{"type":"string","enum":["embedding.openai","embedding.voyage","rerank.voyage","ocr.mistral","exa.search","exa.contents","tinyfish.fetch","tinyfish.browser","tinyfish.agent","dataforseo.serp","dataforseo.ai-keywords","dataforseo.llm-responses","dataforseo.app-info","dataforseo.app-search","dataforseo.backlinks","dataforseo.business-reviews","dataforseo.business-pinterest","dataforseo.content-analysis","dataforseo.technologies","dataforseo.keyword-data","dataforseo.labs","dataforseo.amazon","dataforseo.onpage","gptimage.generate","rembg.remove-background","seedance.generate","mm.i2v","wan.t2v","wan.i2v","happyhorse.t2v","minimax.h3","fish-audio.transcribe","code-review","exa.answer","googlemap.geocode","googlemap.places","agentmail.list-inboxes","tinyfish.search","tinyfish.profile-list","meta.transcribe","minimax.tts","elevenlabs.sound","zai.transcribe","openai.transcribe","fish-audio.tts","google.image","openai.image-2.5","wan.image","logo.lookup","openmeteo.weather","frankfurter.fx","dictionary.define","openlibrary.search","googledns.resolve","qrserver.create","social-boost.catalog"]},"additionalProperties":{"type":"string","enum":["always_allow","always_ask","auto"]}},"nativeToolPolicy":{"description":"Owner-only permission for native pod tools; omitted defaults to always_allow. Supported by Claude Code and Codex after native approval rollout.","type":"string","enum":["always_allow","always_ask"]},"hiringPolicy":{"description":"Whether this agent's sessions may bring in other agents as helpers; omitted defaults to allow. deny makes the agent work alone.","type":"string","enum":["allow","deny"]},"harness":{"description":"workspace_acp only: the public id (hrn_…) of the workspace harness to pin. Required when agentType is workspace_acp.","type":"string","minLength":1}}},"PatchAgent":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"displayName":{"type":"string","maxLength":60},"capabilities":{"type":"array","items":{"type":"string","enum":["embedding.openai","embedding.voyage","rerank.voyage","ocr.mistral","exa.search","exa.contents","tinyfish.fetch","tinyfish.browser","tinyfish.agent","dataforseo.serp","dataforseo.ai-keywords","dataforseo.llm-responses","dataforseo.app-info","dataforseo.app-search","dataforseo.backlinks","dataforseo.business-reviews","dataforseo.business-pinterest","dataforseo.content-analysis","dataforseo.technologies","dataforseo.keyword-data","dataforseo.labs","dataforseo.amazon","dataforseo.onpage","gptimage.generate","rembg.remove-background","seedance.generate","mm.i2v","wan.t2v","wan.i2v","happyhorse.t2v","minimax.h3","fish-audio.transcribe","code-review","exa.answer","googlemap.geocode","googlemap.places","agentmail.list-inboxes","tinyfish.search","tinyfish.profile-list","meta.transcribe","minimax.tts","elevenlabs.sound","zai.transcribe","openai.transcribe","fish-audio.tts","google.image","openai.image-2.5","wan.image","logo.lookup","openmeteo.weather","frankfurter.fx","dictionary.define","openlibrary.search","googledns.resolve","qrserver.create","social-boost.catalog"]}},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"environmentId":{"description":"The environment sessions of this agent boot in when they name none; null clears, omitted preserves. Applies to sessions created afterwards.","anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"vaultId":{"description":"The vault every session of this agent carries; null clears, omitted preserves. Applies to sessions created afterwards.","anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"capabilityPolicies":{"type":"object","propertyNames":{"type":"string","enum":["embedding.openai","embedding.voyage","rerank.voyage","ocr.mistral","exa.search","exa.contents","tinyfish.fetch","tinyfish.browser","tinyfish.agent","dataforseo.serp","dataforseo.ai-keywords","dataforseo.llm-responses","dataforseo.app-info","dataforseo.app-search","dataforseo.backlinks","dataforseo.business-reviews","dataforseo.business-pinterest","dataforseo.content-analysis","dataforseo.technologies","dataforseo.keyword-data","dataforseo.labs","dataforseo.amazon","dataforseo.onpage","gptimage.generate","rembg.remove-background","seedance.generate","mm.i2v","wan.t2v","wan.i2v","happyhorse.t2v","minimax.h3","fish-audio.transcribe","code-review","exa.answer","googlemap.geocode","googlemap.places","agentmail.list-inboxes","tinyfish.search","tinyfish.profile-list","meta.transcribe","minimax.tts","elevenlabs.sound","zai.transcribe","openai.transcribe","fish-audio.tts","google.image","openai.image-2.5","wan.image","logo.lookup","openmeteo.weather","frankfurter.fx","dictionary.define","openlibrary.search","googledns.resolve","qrserver.create","social-boost.catalog"]},"additionalProperties":{"type":"string","enum":["always_allow","always_ask","auto"]}},"nativeToolPolicy":{"description":"Owner-only permission for native pod tools. Omitted preserves; changing permission requires idle sessions. There is no session override.","type":"string","enum":["always_allow","always_ask"]},"hiringPolicy":{"description":"Whether this agent's sessions may bring in other agents as helpers. Omitted preserves. deny refuses the next helper a session tries to start; sessions created afterwards are not told how to hire.","type":"string","enum":["allow","deny"]},"harnessVersion":{"type":"string","minLength":1},"reasoningEffort":{"description":"Harness-native reasoning effort; null clears the pin and applies model-compatible normalization. Applies from the next provision/restart. Allowed values depend on agentType — agoragentic_acp: not supported; amp_acp: not supported; auggie: not supported; autohand: not supported; cline: not supported; codebuddy_code: not supported; cortex_code: not supported; corust_agent: not supported; crow_cli: not supported; cursor: not supported; deepagents: not supported; devin: not supported; dimcode: not supported; dirac: not supported; factory_droid: not supported; fast_agent: not supported; gemini: not supported; github_copilot_cli: not supported; glm_acp_agent: not supported; antigravity_acp: not supported; goose: not supported; grok_build: not supported; harn: not supported; junie: not supported; kilo: not supported; kimchi: not supported; minimax_code: not supported; minion_code: not supported; mistral_vibe: not supported; nova: not supported; poolside: not supported; qoder: not supported; qwen_code: not supported; sigit: not supported; stakpak: not supported; vtcode: not supported; code_assistant: not supported; docker_cagent: not supported; kiro: not supported; muse_code: not supported; openhands: not supported; hermes: none/minimal/low/medium/high/xhigh/max/ultra; claude_code: low/medium/high/xhigh/max; codex: none/minimal/low/medium/high/xhigh/max; openclaw: not supported; jev: not supported; pi: off/minimal/low/medium/high/xhigh/max; dsh: not supported; kimi_code: not supported; opencode: none/minimal/low/medium/high/xhigh/max; workspace_acp: not supported; models: claude-haiku-4-5: not supported; gemini-3.8-flash: low/medium/high; gemini-3.5-flash: low/medium/high; glm-5.3: low/high/max; glm-5.3-flash: low/high/max; grok-4.6: low/medium/high; grok-4.7: low/medium/high/xhigh; codex/hermes + gpt-6.1-sol: low/medium/high/xhigh/max","anyOf":[{"type":"string","enum":["none","off","minimal","low","medium","high","xhigh","max","ultra"]},{"type":"null"}]},"skills":{"description":"Replaces the whole skills array; omitted preserves. Applies from the next provision.","type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"skill"},"skillId":{"type":"string","minLength":1},"version":{"default":"latest","type":"string","minLength":1}},"required":["type","skillId"]},{"type":"object","properties":{"type":{"type":"string","const":"github"},"url":{"type":"string","format":"uri"},"ref":{"description":"Branch or commit SHA; default branch when omitted.","type":"string","minLength":1},"tokenSecretRef":{"description":"Agent secret key holding a clone token for private repos.","type":"string","minLength":1}},"required":["type","url"]}]}},"mcpServers":{"description":"Replaces the whole MCP server list; omitted preserves. Applies from the next provision.","maxItems":20,"type":"array","items":{"type":"object","properties":{"type":{"default":"url","type":"string","const":"url"},"name":{"type":"string","minLength":1,"maxLength":255},"url":{"type":"string","format":"uri"},"tools":{"type":"object","properties":{"include":{"default":[],"maxItems":200,"type":"array","items":{"type":"string","minLength":1}},"exclude":{"default":[],"maxItems":200,"type":"array","items":{"type":"string","minLength":1}}}}},"required":["name","url"]}},"hooks":{"description":"Replaces the whole hook list; omitted preserves. Applies from the next provision.","maxItems":20,"type":"array","items":{"type":"object","properties":{"event":{"type":"string","enum":["pre_session_start","session_start","user_prompt_submit","pre_tool_use","post_tool_use","stop","session_end"]},"command":{"type":"string","minLength":1,"maxLength":4000},"matcher":{"type":"string","minLength":1,"maxLength":255},"timeout_s":{"type":"integer","minimum":1,"maximum":600}},"required":["event","command"],"additionalProperties":false}},"expectedVersion":{"type":"integer","minimum":1,"maximum":9007199254740991}}},"CreateSession":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"agent":{"type":"string","minLength":1,"description":"An agent id, or \"@handle\" for an agent from the catalog (GET /catalog/agents). A handle that names a platform engine uses the workspace's agent for that engine, created on first use."},"llm":{"description":"Model for this session (a current model for the agent's harness). Omitted = the agent's model","type":"string","minLength":1},"reasoningEffort":{"description":"Reasoning effort for this session; omitted or null inherits the agent's setting normalized for the target model. Explicit values must fit both harness and target model - agoragentic_acp: not supported; amp_acp: not supported; auggie: not supported; autohand: not supported; cline: not supported; codebuddy_code: not supported; cortex_code: not supported; corust_agent: not supported; crow_cli: not supported; cursor: not supported; deepagents: not supported; devin: not supported; dimcode: not supported; dirac: not supported; factory_droid: not supported; fast_agent: not supported; gemini: not supported; github_copilot_cli: not supported; glm_acp_agent: not supported; antigravity_acp: not supported; goose: not supported; grok_build: not supported; harn: not supported; junie: not supported; kilo: not supported; kimchi: not supported; minimax_code: not supported; minion_code: not supported; mistral_vibe: not supported; nova: not supported; poolside: not supported; qoder: not supported; qwen_code: not supported; sigit: not supported; stakpak: not supported; vtcode: not supported; code_assistant: not supported; docker_cagent: not supported; kiro: not supported; muse_code: not supported; openhands: not supported; hermes: none/minimal/low/medium/high/xhigh/max/ultra; claude_code: low/medium/high/xhigh/max; codex: none/minimal/low/medium/high/xhigh/max; openclaw: not supported; jev: not supported; pi: off/minimal/low/medium/high/xhigh/max; dsh: not supported; kimi_code: not supported; opencode: none/minimal/low/medium/high/xhigh/max; workspace_acp: not supported; models: claude-haiku-4-5: not supported; gemini-3.8-flash: low/medium/high; gemini-3.5-flash: low/medium/high; glm-5.3: low/high/max; glm-5.3-flash: low/high/max; grok-4.6: low/medium/high; grok-4.7: low/medium/high/xhigh; codex/hermes + gpt-6.1-sol: low/medium/high/xhigh/max","anyOf":[{"type":"string","enum":["none","off","minimal","low","medium","high","xhigh","max","ultra"]},{"type":"null"}]},"title":{"type":"string","maxLength":120},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"idleTimeoutSeconds":{"description":"Seconds this session's machine stays awake after a turn ends before it is paused (60-86400; omitted = the platform default of 60). A paused machine wakes on the next message; apps the agent serves on exposed ports are unreachable while it is paused, so set this to how long people keep using them after the agent finishes","type":"integer","minimum":60,"maximum":86400},"instructions":{"maxItems":20,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"pattern":".*\\.md$"},"content":{"default":"","type":"string"}},"required":["name"]}},"initial_events":{"maxItems":50,"type":"array","items":{"type":"object","properties":{"type":{"type":"string","const":"user.message"},"content":{"minItems":1,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"text":{"type":"string","minLength":1}},"required":["type","text"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"image"},"source":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"base64"},"media_type":{"type":"string","minLength":1},"data":{"type":"string","minLength":1}},"required":["type","media_type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"url"},"url":{"type":"string","minLength":1}},"required":["type","url"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"file"},"file_id":{"type":"string","minLength":1}},"required":["type","file_id"],"additionalProperties":false}]}},"required":["type","source"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"document"},"source":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"base64"},"media_type":{"type":"string","minLength":1},"data":{"type":"string","minLength":1}},"required":["type","media_type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"text"},"media_type":{"default":"text/plain","type":"string","const":"text/plain"},"data":{"type":"string","minLength":1}},"required":["type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"url"},"url":{"type":"string","minLength":1}},"required":["type","url"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"file"},"file_id":{"type":"string","minLength":1}},"required":["type","file_id"],"additionalProperties":false}]},"title":{"type":["string","null"]},"context":{"type":["string","null"]}},"required":["type","source"],"additionalProperties":false}]}},"interaction_mode":{"anyOf":[{"type":"string","enum":["plan","build"]},{"type":"null"}]}},"required":["type","content"],"additionalProperties":false}},"provision":{"description":"eager (default) boots the sandbox as soon as the row exists; deferred leaves the session idle with no pod until its first turn, so a session waiting on a gate or a schedule costs nothing while it waits. Ignored when initial_events start the first turn","type":"string","enum":["eager","deferred"]},"environment_id":{"type":"string","minLength":1},"vault_ids":{"maxItems":10,"type":"array","items":{"type":"string","minLength":1}},"vcpus":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"memoryMb":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"subscriptionApiFallback":{"description":"After every subscription account is exhausted, continue on the same model using the paid platform API; wallet and session budget still apply","type":"boolean"},"modelBilling":{"description":"Who pays for model calls: platform wallet or the user's connected subscription. Omitted = auto-apply (a connected subscription with \"use for new agents\" powers eligible compositions)","type":"string","enum":["platform","account"]},"budget":{"description":"Hard spend cap for this session. Attachable only at create; changeable or removable later via PATCH (removal is one-way)","type":"object","properties":{"type":{"type":"string","const":"limit"},"max_list_cost":{"type":"object","properties":{"amount":{"type":"string","minLength":1,"maxLength":15,"description":"Whole US cents as an integer decimal string, e.g. \"125\" for $1.25"},"currency":{"type":"string","const":"USD"}},"required":["amount","currency"]}},"required":["type","max_list_cost"]},"payer":{"description":"Which balance pays for the session, in a team workspace that has a wallet of its own: \"workspace\" (the default there) or \"personal\", the caller's own. Decided once, here, and shown as `payer` on the session and its task. \"workspace\" where the workspace has no wallet is refused with 409 workspace_wallet_unavailable.","type":"string","enum":["personal","workspace"]},"defaults":{"description":"Whether the session also starts with its workspace's defaults: the default environment when none is named, the default vault when it holds a secret, and the always-available files and skills. \"none\" attaches only what this request names. Omitted means \"workspace\".","type":"string","enum":["workspace","none"]},"resources":{"description":"Files, GitHub repositories, and team Memory Stores attached before the first turn (max 100 create-time resources; max 8 memory stores). `{type:\"file\", file_id, mount_path?}` copies an upload read-only to `/workspace<mount_path>` (default `/workspace/<file_id>`); `{type:\"github_repository\", url, authorization_token?, checkout?: {type:\"branch\", name} | {type:\"commit\", sha}, mount_path?}` clones `https://github.com/{owner}/{repo}` to `/workspace<mount_path>` (default `/workspace/<repo>`); the token never enters the sandbox. `{type:\"memory_store\", memory_store_id, access:\"read_only\"|\"read_write\", mount_path?, instructions?}` attaches a creation-time snapshot under `/mnt/memory/` (default `/mnt/memory/<memory_store_id>`; 8 MiB total per Session). `read_write` explicitly grants the session-scoped Agent API permission to update this store; the mounted snapshot remains read-only.","maxItems":100,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"file"},"file_id":{"type":"string","minLength":1,"maxLength":128},"mount_path":{"anyOf":[{"type":"string","minLength":1,"maxLength":4096},{"type":"null"}]}},"required":["type","file_id"]},{"type":"object","properties":{"type":{"type":"string","const":"github_repository"},"url":{"type":"string","minLength":1,"maxLength":2048},"authorization_token":{"type":"string","minLength":1,"maxLength":1024},"checkout":{"anyOf":[{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"branch"},"name":{"type":"string","minLength":1,"maxLength":255}},"required":["type","name"]},{"type":"object","properties":{"type":{"type":"string","const":"commit"},"sha":{"type":"string","minLength":7,"maxLength":64}},"required":["type","sha"]}]},{"type":"null"}]},"mount_path":{"anyOf":[{"type":"string","minLength":1,"maxLength":4096},{"type":"null"}]}},"required":["type","url"]},{"type":"object","properties":{"type":{"type":"string","const":"memory_store"},"memory_store_id":{"type":"string","minLength":1,"maxLength":255},"access":{"type":"string","enum":["read_only","read_write"]},"instructions":{"type":"string","maxLength":4096},"mount_path":{"anyOf":[{"type":"string","minLength":1,"maxLength":4096},{"type":"null"}]}},"required":["type","memory_store_id","access"]}]}}},"required":["agent"]},"PatchSession":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"title":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"idleTimeoutSeconds":{"description":"Seconds this session's machine stays awake after a turn ends before it is paused (60-86400; omitted = the platform default of 60). A paused machine wakes on the next message; apps the agent serves on exposed ports are unreachable while it is paused, so set this to how long people keep using them after the agent finishes; null clears back to the platform default. Applies from the next time the session goes idle","anyOf":[{"type":"integer","minimum":60,"maximum":86400},{"type":"null"}]},"llm":{"description":"Switch this session's model (a current model for its harness; the agent's model is unchanged). Applies from the next turn","type":"string","minLength":1},"reasoningEffort":{"description":"Session-level reasoning effort; null clears to the agent's setting normalized for the target model. Applies from the next turn. Explicit values must fit both harness and target model — agoragentic_acp: not supported; amp_acp: not supported; auggie: not supported; autohand: not supported; cline: not supported; codebuddy_code: not supported; cortex_code: not supported; corust_agent: not supported; crow_cli: not supported; cursor: not supported; deepagents: not supported; devin: not supported; dimcode: not supported; dirac: not supported; factory_droid: not supported; fast_agent: not supported; gemini: not supported; github_copilot_cli: not supported; glm_acp_agent: not supported; antigravity_acp: not supported; goose: not supported; grok_build: not supported; harn: not supported; junie: not supported; kilo: not supported; kimchi: not supported; minimax_code: not supported; minion_code: not supported; mistral_vibe: not supported; nova: not supported; poolside: not supported; qoder: not supported; qwen_code: not supported; sigit: not supported; stakpak: not supported; vtcode: not supported; code_assistant: not supported; docker_cagent: not supported; kiro: not supported; muse_code: not supported; openhands: not supported; hermes: none/minimal/low/medium/high/xhigh/max/ultra; claude_code: low/medium/high/xhigh/max; codex: none/minimal/low/medium/high/xhigh/max; openclaw: not supported; jev: not supported; pi: off/minimal/low/medium/high/xhigh/max; dsh: not supported; kimi_code: not supported; opencode: none/minimal/low/medium/high/xhigh/max; workspace_acp: not supported; models: claude-haiku-4-5: not supported; gemini-3.8-flash: low/medium/high; gemini-3.5-flash: low/medium/high; glm-5.3: low/high/max; glm-5.3-flash: low/high/max; grok-4.6: low/medium/high; grok-4.7: low/medium/high/xhigh; codex/hermes + gpt-6.1-sol: low/medium/high/xhigh/max","anyOf":[{"type":"string","enum":["none","off","minimal","low","medium","high","xhigh","max","ultra"]},{"type":"null"}]},"subscriptionApiFallback":{"description":"After every subscription account is exhausted, continue on the same model using the paid platform API; wallet and session budget still apply","type":"boolean"},"modelBilling":{"description":"Who pays for model calls; switching restarts the agent's engine in place","type":"string","enum":["platform","account"]},"budget":{"description":"Change the spend cap (must be strictly above consumed cost) or null to remove it — removal is one-way","anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"limit"},"max_list_cost":{"type":"object","properties":{"amount":{"type":"string","minLength":1,"maxLength":15,"description":"Whole US cents as an integer decimal string, e.g. \"125\" for $1.25"},"currency":{"type":"string","const":"USD"}},"required":["amount","currency"]}},"required":["type","max_list_cost"]},{"type":"null"}]}}},"AddSessionResource":{"$schema":"http://json-schema.org/draft-07/schema#","oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"file"},"file_id":{"type":"string","minLength":1,"maxLength":128},"mount_path":{"anyOf":[{"type":"string","minLength":1,"maxLength":4096},{"type":"null"}]}},"required":["type","file_id"]},{"type":"object","properties":{"type":{"type":"string","const":"github_repository"},"url":{"type":"string","minLength":1,"maxLength":2048},"authorization_token":{"type":"string","minLength":1,"maxLength":1024},"checkout":{"anyOf":[{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"branch"},"name":{"type":"string","minLength":1,"maxLength":255}},"required":["type","name"]},{"type":"object","properties":{"type":{"type":"string","const":"commit"},"sha":{"type":"string","minLength":7,"maxLength":64}},"required":["type","sha"]}]},{"type":"null"}]},"mount_path":{"anyOf":[{"type":"string","minLength":1,"maxLength":4096},{"type":"null"}]}},"required":["type","url"]},{"type":"object","properties":{"type":{"type":"string","const":"memory_store"},"memory_store_id":{"type":"string","minLength":1,"maxLength":255},"access":{"type":"string","enum":["read_only","read_write"]},"instructions":{"type":"string","maxLength":4096},"mount_path":{"anyOf":[{"type":"string","minLength":1,"maxLength":4096},{"type":"null"}]}},"required":["type","memory_store_id","access"]}]},"UpdateSessionResource":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"authorization_token":{"type":"string","minLength":1,"maxLength":1024}},"required":["authorization_token"]},"PutPrompt":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"prompt":{"type":"string","maxLength":100000}},"required":["prompt"]},"PutSecret":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"value":{"type":"string","minLength":1,"maxLength":10000},"description":{"type":"string","maxLength":500}},"required":["value"]},"PutModelSubscription":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"credential":{"type":"string","minLength":1,"maxLength":100000},"label":{"type":"string","maxLength":60}},"required":["credential"]},"AddModelSubscription":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"credential":{"type":"string","minLength":1,"maxLength":100000},"label":{"type":"string","maxLength":60},"provider":{"type":"string","enum":["anthropic","openai","cursor","xai","meta"]}},"required":["credential","provider"]},"PatchModelSubscription":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"useForNewAgents":{"type":"boolean"},"label":{"type":"string","maxLength":60}}},"CreateUniverse":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"slug":{"type":"string","minLength":3,"maxLength":40,"pattern":"^[a-z0-9][a-z0-9-]*[a-z0-9]$"},"name":{"type":"string","maxLength":80}},"required":["slug"]},"CreateRoutine":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":256},"description":{"type":"string","maxLength":2048},"metadata":{"type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{"type":"string","maxLength":512}},"target":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"new_session"},"agent":{"type":"string","minLength":1},"environment_id":{"type":"string","minLength":1},"vault_ids":{"maxItems":10,"type":"array","items":{"type":"string","minLength":1}}},"required":["type","agent"]},{"type":"object","properties":{"type":{"type":"string","const":"session"},"session_id":{"type":"string","minLength":1}},"required":["type","session_id"]}]},"initial_events":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"object","properties":{"type":{"type":"string","const":"user.message"},"content":{"minItems":1,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"text":{"type":"string","minLength":1}},"required":["type","text"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"image"},"source":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"base64"},"media_type":{"type":"string","minLength":1},"data":{"type":"string","minLength":1}},"required":["type","media_type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"url"},"url":{"type":"string","minLength":1}},"required":["type","url"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"file"},"file_id":{"type":"string","minLength":1}},"required":["type","file_id"],"additionalProperties":false}]}},"required":["type","source"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"document"},"source":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"base64"},"media_type":{"type":"string","minLength":1},"data":{"type":"string","minLength":1}},"required":["type","media_type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"text"},"media_type":{"default":"text/plain","type":"string","const":"text/plain"},"data":{"type":"string","minLength":1}},"required":["type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"url"},"url":{"type":"string","minLength":1}},"required":["type","url"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"file"},"file_id":{"type":"string","minLength":1}},"required":["type","file_id"],"additionalProperties":false}]},"title":{"type":["string","null"]},"context":{"type":["string","null"]}},"required":["type","source"],"additionalProperties":false}]}},"interaction_mode":{"anyOf":[{"type":"string","enum":["plan","build"]},{"type":"null"}]}},"required":["type","content"],"additionalProperties":false}},"schedule":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"cron"},"expression":{"type":"string","minLength":1,"maxLength":256},"timezone":{"type":"string","minLength":1}},"required":["type","expression","timezone"]},{"type":"null"}]},"budget":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"limit"},"max_list_cost":{"type":"object","properties":{"amount":{"type":"string","minLength":1,"maxLength":15,"description":"Whole US cents as an integer decimal string, e.g. \"125\" for $1.25"},"currency":{"type":"string","const":"USD"}},"required":["amount","currency"]}},"required":["type","max_list_cost"]},{"type":"null"}]}},"required":["name","target","initial_events"]},"PatchRoutine":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":256},"description":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}]},"metadata":{"type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}]}},"target":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"new_session"},"agent":{"type":"string","minLength":1},"environment_id":{"type":"string","minLength":1},"vault_ids":{"maxItems":10,"type":"array","items":{"type":"string","minLength":1}}},"required":["type","agent"]},{"type":"object","properties":{"type":{"type":"string","const":"session"},"session_id":{"type":"string","minLength":1}},"required":["type","session_id"]}]},"initial_events":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"object","properties":{"type":{"type":"string","const":"user.message"},"content":{"minItems":1,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"text":{"type":"string","minLength":1}},"required":["type","text"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"image"},"source":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"base64"},"media_type":{"type":"string","minLength":1},"data":{"type":"string","minLength":1}},"required":["type","media_type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"url"},"url":{"type":"string","minLength":1}},"required":["type","url"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"file"},"file_id":{"type":"string","minLength":1}},"required":["type","file_id"],"additionalProperties":false}]}},"required":["type","source"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"document"},"source":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"base64"},"media_type":{"type":"string","minLength":1},"data":{"type":"string","minLength":1}},"required":["type","media_type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"text"},"media_type":{"default":"text/plain","type":"string","const":"text/plain"},"data":{"type":"string","minLength":1}},"required":["type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"url"},"url":{"type":"string","minLength":1}},"required":["type","url"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"file"},"file_id":{"type":"string","minLength":1}},"required":["type","file_id"],"additionalProperties":false}]},"title":{"type":["string","null"]},"context":{"type":["string","null"]}},"required":["type","source"],"additionalProperties":false}]}},"interaction_mode":{"anyOf":[{"type":"string","enum":["plan","build"]},{"type":"null"}]}},"required":["type","content"],"additionalProperties":false}},"schedule":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"cron"},"expression":{"type":"string","minLength":1,"maxLength":256},"timezone":{"type":"string","minLength":1}},"required":["type","expression","timezone"]},{"type":"null"}]},"budget":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"limit"},"max_list_cost":{"type":"object","properties":{"amount":{"type":"string","minLength":1,"maxLength":15,"description":"Whole US cents as an integer decimal string, e.g. \"125\" for $1.25"},"currency":{"type":"string","const":"USD"}},"required":["amount","currency"]}},"required":["type","max_list_cost"]},{"type":"null"}]}}},"CreateWebhookEndpoint":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":2048},"events":{"minItems":1,"maxItems":32,"type":"array","items":{"type":"string","minLength":1}}},"required":["url","events"]},"PatchWebhookEndpoint":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":2048},"events":{"minItems":1,"maxItems":32,"type":"array","items":{"type":"string","minLength":1}},"status":{"type":"string","enum":["active","disabled"]}}},"SendMessages":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"parts":{"minItems":1,"type":"array","items":{"oneOf":[{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"text"},"text":{"default":"","type":"string"},"stream_id":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"stream_index":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]}},"required":["index","type"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"reasoning"},"text":{"default":"","type":"string"},"redacted":{"default":false,"type":"boolean"},"stream_id":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"stream_index":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]}},"required":["index","type"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"tool_call"},"call_id":{"type":"string"},"tool_name":{"type":"string"},"args":{"default":{},"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"args_partial":{"type":["string","null"]}},"required":["index","type","call_id","tool_name"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"tool_result"},"call_id":{"type":"string"},"tool_name":{"type":"string"},"status":{"default":"ok","type":"string","enum":["ok","error"]},"result":{"default":{},"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["index","type","call_id","tool_name"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"file"},"name":{"type":"string"},"media_type":{"type":"string"},"uri":{"type":["string","null"]},"data":{"type":["string","null"]},"size_bytes":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]}},"required":["index","type","name","media_type"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"image"},"media_type":{"type":"string"},"uri":{"type":["string","null"]},"data":{"type":["string","null"]},"alt":{"type":["string","null"]},"width":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]}},"required":["index","type","media_type"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"video"},"media_type":{"type":"string"},"uri":{"type":["string","null"]},"data":{"type":["string","null"]},"alt":{"type":["string","null"]},"width":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"duration_ms":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"size_bytes":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"thumbnail_uri":{"type":["string","null"]}},"required":["index","type","media_type"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"status"},"level":{"type":"string","enum":["thinking","working","waiting","idle","done"]},"text":{"type":["string","null"]}},"required":["index","type","level"]},{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"type":{"type":"string","const":"error"},"code":{"type":"string"},"message":{"type":"string"},"retryable":{"default":false,"type":"boolean"}},"required":["index","type","code","message"]}]}}},"required":["parts"]},"SendEvents":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"events":{"minItems":1,"maxItems":50,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"user.message"},"content":{"minItems":1,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"text":{"type":"string","minLength":1}},"required":["type","text"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"image"},"source":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"base64"},"media_type":{"type":"string","minLength":1},"data":{"type":"string","minLength":1}},"required":["type","media_type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"url"},"url":{"type":"string","minLength":1}},"required":["type","url"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"file"},"file_id":{"type":"string","minLength":1}},"required":["type","file_id"],"additionalProperties":false}]}},"required":["type","source"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"document"},"source":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"base64"},"media_type":{"type":"string","minLength":1},"data":{"type":"string","minLength":1}},"required":["type","media_type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"text"},"media_type":{"default":"text/plain","type":"string","const":"text/plain"},"data":{"type":"string","minLength":1}},"required":["type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"url"},"url":{"type":"string","minLength":1}},"required":["type","url"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"file"},"file_id":{"type":"string","minLength":1}},"required":["type","file_id"],"additionalProperties":false}]},"title":{"type":["string","null"]},"context":{"type":["string","null"]}},"required":["type","source"],"additionalProperties":false}]}},"interaction_mode":{"anyOf":[{"type":"string","enum":["plan","build"]},{"type":"null"}]}},"required":["type","content"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"system.message"},"content":{"minItems":1,"maxItems":1000,"type":"array","items":{"type":"object","properties":{"type":{"type":"string","const":"text"},"text":{"type":"string","minLength":1}},"required":["type","text"],"additionalProperties":false}}},"required":["type","content"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"user.interrupt"},"mode":{"type":"string","enum":["immediate","save"]}},"required":["type"],"additionalProperties":false}]}},"requireIdle":{"type":"boolean"}},"required":["events"],"additionalProperties":false},"GoalInput":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"objective":{"type":"string","minLength":1,"maxLength":4000,"description":"What the agent should work toward, in the user's words"},"criteria":{"description":"Independently checkable requirements; omitted = derived from the objective","maxItems":20,"type":"array","items":{"anyOf":[{"type":"string","minLength":1,"maxLength":500},{"type":"object","properties":{"text":{"type":"string","minLength":1,"maxLength":500,"description":"What the criterion requires, in words"},"command":{"description":"Shell command run in the session's workspace; exit 0 means the criterion is met","type":"string","minLength":1,"maxLength":1000}},"required":["text"]}]}},"max_iterations":{"description":"Self-started turns this goal may take before it stops. Omitted = 20; null = no iteration ceiling","anyOf":[{"type":"integer","minimum":1,"maximum":200},{"type":"null"}]},"max_no_progress":{"description":"Consecutive turns without a tool call before stopping. Omitted = 3; null = no no-progress ceiling","anyOf":[{"type":"integer","minimum":1,"maximum":20},{"type":"null"}]},"max_spend":{"description":"Spend ceiling for this goal; null = none","anyOf":[{"type":"object","properties":{"amount":{"type":"string","minLength":1,"maxLength":15,"description":"Whole US cents as an integer decimal string, e.g. \"500\" for $5.00"},"currency":{"type":"string","const":"USD"}},"required":["amount","currency"]},{"type":"null"}]},"max_tokens":{"anyOf":[{"type":"integer","minimum":1,"maximum":9007199254740991,"description":"Token ceiling for this goal: uncached input plus output, counted from the goal's start"},{"type":"null"}]},"max_duration_minutes":{"description":"Wall-clock ceiling from the goal's start, extended by any time it spends paused","anyOf":[{"type":"integer","minimum":1,"maximum":10080},{"type":"null"}]}},"required":["objective"]},"CreatePolicyRule":{"$schema":"http://json-schema.org/draft-07/schema#","oneOf":[{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"enabled":{"default":true,"type":"boolean"},"position":{"default":0,"type":"integer","minimum":0,"maximum":9999},"kind":{"type":"string","const":"TOOL_CALL"},"config":{"type":"object","properties":{"action":{"type":"string","enum":["allow","ask","deny"]},"matcher":{"type":"string","minLength":1,"maxLength":255},"commandPatterns":{"maxItems":20,"type":"array","items":{"type":"string","minLength":1,"maxLength":500}}},"required":["action"],"additionalProperties":false}},"required":["name","kind","config"]},{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"enabled":{"default":true,"type":"boolean"},"position":{"default":0,"type":"integer","minimum":0,"maximum":9999},"kind":{"type":"string","const":"SPEND_CAP"},"config":{"type":"object","properties":{"warnUsdMicros":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"hardCapUsdMicros":{"type":"integer","minimum":1,"maximum":9007199254740991}},"required":["hardCapUsdMicros"],"additionalProperties":false}},"required":["name","kind","config"]},{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"enabled":{"default":true,"type":"boolean"},"position":{"default":0,"type":"integer","minimum":0,"maximum":9999},"kind":{"type":"string","const":"CALL_COUNT"},"config":{"type":"object","properties":{"limitPerSession":{"type":"integer","minimum":1,"maximum":100000}},"required":["limitPerSession"],"additionalProperties":false}},"required":["name","kind","config"]},{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"enabled":{"default":true,"type":"boolean"},"position":{"default":0,"type":"integer","minimum":0,"maximum":9999},"kind":{"type":"string","const":"CAPABILITY"},"config":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","enum":["allow","ask","deny"]}}},"required":["name","kind","config"]}],"description":"One rule, chosen by `kind`. TOOL_CALL: {action: allow|ask|deny, matcher?: tool names joined by |, commandPatterns?: shell globs}. SPEND_CAP: {hardCapUsdMicros, warnUsdMicros?} per session, warn below the cap. CALL_COUNT: {limitPerSession}. CAPABILITY: {<capability id>: allow|ask|deny}; platform.* ids accept allow or deny."},"PatchPolicyRule":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"enabled":{"type":"boolean"},"position":{"type":"integer","minimum":0,"maximum":9999},"config":{"anyOf":[{"type":"object","properties":{"action":{"type":"string","enum":["allow","ask","deny"]},"matcher":{"type":"string","minLength":1,"maxLength":255},"commandPatterns":{"maxItems":20,"type":"array","items":{"type":"string","minLength":1,"maxLength":500}}},"required":["action"],"additionalProperties":false},{"type":"object","properties":{"warnUsdMicros":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"hardCapUsdMicros":{"type":"integer","minimum":1,"maximum":9007199254740991}},"required":["hardCapUsdMicros"],"additionalProperties":false},{"type":"object","properties":{"limitPerSession":{"type":"integer","minimum":1,"maximum":100000}},"required":["limitPerSession"],"additionalProperties":false},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","enum":["allow","ask","deny"]}}]}},"description":"Any of name, enabled, position and config. `kind` cannot change; a new config must fit the rule's kind."},"PolicyRule":{"type":"object","required":["id","name","kind","enabled","config","layer","position","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["TOOL_CALL","SPEND_CAP","CALL_COUNT","CAPABILITY"]},"enabled":{"type":"boolean"},"config":{"type":"object"},"layer":{"type":"string","enum":["workspace","agent","session"]},"position":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"GoalPatch":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"objective":{"type":"string","minLength":1,"maxLength":4000},"criteria":{"minItems":1,"maxItems":20,"type":"array","items":{"anyOf":[{"type":"string","minLength":1,"maxLength":500},{"type":"object","properties":{"text":{"type":"string","minLength":1,"maxLength":500,"description":"What the criterion requires, in words"},"command":{"description":"Shell command run in the session's workspace; exit 0 means the criterion is met","type":"string","minLength":1,"maxLength":1000}},"required":["text"]}]}},"max_iterations":{"anyOf":[{"type":"integer","minimum":1,"maximum":200},{"type":"null"}]},"max_no_progress":{"anyOf":[{"type":"integer","minimum":1,"maximum":20},{"type":"null"}]},"max_spend":{"anyOf":[{"type":"object","properties":{"amount":{"type":"string","minLength":1,"maxLength":15,"description":"Whole US cents as an integer decimal string, e.g. \"500\" for $5.00"},"currency":{"type":"string","const":"USD"}},"required":["amount","currency"]},{"type":"null"}]},"max_tokens":{"anyOf":[{"type":"integer","minimum":1,"maximum":9007199254740991,"description":"Token ceiling for this goal: uncached input plus output, counted from the goal's start"},{"type":"null"}]},"max_duration_minutes":{"anyOf":[{"type":"integer","minimum":1,"maximum":10080},{"type":"null"}]}}},"SendEventsResult":{"type":"object","required":["data"],"properties":{"data":{"type":"array","description":"One echo per event, in order, in the events-history shape","items":{"allOf":[{"$ref":"#/components/schemas/Event"},{"type":"object","properties":{"admission":{"type":"string","enum":["created","replayed"],"description":"Only on a requireIdle user.message echo: created means this POST committed the exclusive input; replayed means the idempotency key already named one. This field is absent from history and SSE."}}}]}}}},"Whoami":{"type":"object","required":["user","universe","scopes","auth"],"properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"name":{"type":["string","null"]}}},"universe":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"isPersonal":{"type":"boolean"}}},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","admin"]}},"auth":{"type":"string","enum":["token","session"]}}},"Universe":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"isPersonal":{"type":"boolean","description":"The workspace is its owner's default workspace"},"isDefault":{"type":"boolean","description":"The workspace is the caller's own default workspace"},"createdAt":{"type":"string","description":"ISO 8601"}}},"AgentSummary":{"type":"object","properties":{"id":{"type":"string","description":"The agent id (agent_…) — the only address"},"name":{"type":"string"},"displayName":{"type":"string"},"agentType":{"type":"string","description":"Engine — hermes · claude_code · codex · openclaw · pi · dsh · kimi_code · opencode · jev, or any ACP harness (the full vocabulary is the enum on CreateAgent)"},"llm":{"type":"string"},"harnessVersion":{"type":["string","null"],"description":"The engine CLI version this agent's sessions run; PATCH to move to the platform's current version"},"reasoningEffort":{"type":["string","null"],"enum":["none","off","minimal","low","medium","high","xhigh","max","ultra",null],"description":"Harness-native reasoning effort; null = model-compatible fallback for constrained models, otherwise harness default. Applies from the next provision/restart. Allowed values depend on agentType — agoragentic_acp: not supported; amp_acp: not supported; auggie: not supported; autohand: not supported; cline: not supported; codebuddy_code: not supported; cortex_code: not supported; corust_agent: not supported; crow_cli: not supported; cursor: not supported; deepagents: not supported; devin: not supported; dimcode: not supported; dirac: not supported; factory_droid: not supported; fast_agent: not supported; gemini: not supported; github_copilot_cli: not supported; glm_acp_agent: not supported; antigravity_acp: not supported; goose: not supported; grok_build: not supported; harn: not supported; junie: not supported; kilo: not supported; kimchi: not supported; minimax_code: not supported; minion_code: not supported; mistral_vibe: not supported; nova: not supported; poolside: not supported; qoder: not supported; qwen_code: not supported; sigit: not supported; stakpak: not supported; vtcode: not supported; code_assistant: not supported; docker_cagent: not supported; kiro: not supported; muse_code: not supported; openhands: not supported; hermes: none/minimal/low/medium/high/xhigh/max/ultra; claude_code: low/medium/high/xhigh/max; codex: none/minimal/low/medium/high/xhigh/max; openclaw: not supported; jev: not supported; pi: off/minimal/low/medium/high/xhigh/max; dsh: not supported; kimi_code: not supported; opencode: none/minimal/low/medium/high/xhigh/max; workspace_acp: not supported; models: claude-haiku-4-5: not supported; gemini-3.8-flash: low/medium/high; gemini-3.5-flash: low/medium/high; glm-5.3: low/high/max; glm-5.3-flash: low/high/max; grok-4.6: low/medium/high; grok-4.7: low/medium/high/xhigh; codex/hermes + gpt-6.1-sol: low/medium/high/xhigh/max"},"capabilities":{"type":"array","items":{"type":"string","enum":["embedding.openai","embedding.voyage","rerank.voyage","ocr.mistral","exa.search","exa.contents","tinyfish.fetch","tinyfish.browser","tinyfish.agent","dataforseo.serp","dataforseo.ai-keywords","dataforseo.llm-responses","dataforseo.app-info","dataforseo.app-search","dataforseo.backlinks","dataforseo.business-reviews","dataforseo.business-pinterest","dataforseo.content-analysis","dataforseo.technologies","dataforseo.keyword-data","dataforseo.labs","dataforseo.amazon","dataforseo.onpage","gptimage.generate","rembg.remove-background","seedance.generate","mm.i2v","wan.t2v","wan.i2v","happyhorse.t2v","minimax.h3","fish-audio.transcribe","code-review","exa.answer","googlemap.geocode","googlemap.places","agentmail.list-inboxes","tinyfish.search","tinyfish.profile-list","meta.transcribe","minimax.tts","elevenlabs.sound","zai.transcribe","openai.transcribe","fish-audio.tts","google.image","openai.image-2.5","wan.image","logo.lookup","openmeteo.weather","frankfurter.fx","dictionary.define","openlibrary.search","googledns.resolve","qrserver.create","social-boost.catalog"]},"description":"The built-in capabilities this agent is granted — the exact set its sessions may execute (enforced; empty = none). Ids are listed at /docs/capabilities."},"version":{"type":"integer","description":"Bumped on every update; see expectedVersion"},"archived":{"type":"boolean"},"sessionCount":{"type":"integer"},"createdAt":{"type":"string","description":"ISO 8601"}}},"AgentDetail":{"type":"object","description":"Everything in the list item, plus configuration state.","properties":{"id":{"type":"string","description":"The agent id (agent_…) — the only address"},"name":{"type":"string"},"displayName":{"type":"string"},"agentType":{"type":"string"},"llm":{"type":"string"},"harnessVersion":{"type":["string","null"]},"reasoningEffort":{"type":["string","null"],"enum":["none","off","minimal","low","medium","high","xhigh","max","ultra",null]},"version":{"type":"integer"},"archived":{"type":"boolean"},"sessionCount":{"type":"integer"},"createdAt":{"type":"string"},"description":{"type":["string","null"]},"prompt":{"type":["string","null"],"description":"The user prompt layer"},"promptVersion":{"type":["integer","null"]},"capabilities":{"type":"array","items":{"type":"string","enum":["embedding.openai","embedding.voyage","rerank.voyage","ocr.mistral","exa.search","exa.contents","tinyfish.fetch","tinyfish.browser","tinyfish.agent","dataforseo.serp","dataforseo.ai-keywords","dataforseo.llm-responses","dataforseo.app-info","dataforseo.app-search","dataforseo.backlinks","dataforseo.business-reviews","dataforseo.business-pinterest","dataforseo.content-analysis","dataforseo.technologies","dataforseo.keyword-data","dataforseo.labs","dataforseo.amazon","dataforseo.onpage","gptimage.generate","rembg.remove-background","seedance.generate","mm.i2v","wan.t2v","wan.i2v","happyhorse.t2v","minimax.h3","fish-audio.transcribe","code-review","exa.answer","googlemap.geocode","googlemap.places","agentmail.list-inboxes","tinyfish.search","tinyfish.profile-list","meta.transcribe","minimax.tts","elevenlabs.sound","zai.transcribe","openai.transcribe","fish-audio.tts","google.image","openai.image-2.5","wan.image","logo.lookup","openmeteo.weather","frankfurter.fx","dictionary.define","openlibrary.search","googledns.resolve","qrserver.create","social-boost.catalog"]},"description":"The built-in capabilities this agent is granted — the exact set its sessions may execute (enforced; empty = none). Ids are listed at /docs/capabilities."},"capabilityPolicies":{"type":"object","additionalProperties":{"type":"string","enum":["always_allow","always_ask","auto"]},"description":"Per-capability permission policy map; omitted when no entries exist. always_allow: invoke without user confirmation. always_ask: prompt the session owner before every invocation. auto: reserved for future policy evaluation; currently prompts the session owner like always_ask."},"nativeToolPolicy":{"$schema":"http://json-schema.org/draft-07/schema#","type":"string","enum":["always_allow","always_ask"],"description":"Native pod-tool permission, independent of capabilities. Returned on create and detail responses; omitted legacy settings mean always_allow. Only the agent owner can change it, while sessions are idle."},"hiringPolicy":{"$schema":"http://json-schema.org/draft-07/schema#","type":"string","enum":["allow","deny"],"description":"Whether this agent's sessions may bring in other agents as helpers. allow unless set to deny. Returned on create and detail responses."},"mcpServers":{"$schema":"http://json-schema.org/draft-07/schema#","maxItems":20,"type":"array","items":{"type":"object","properties":{"type":{"default":"url","type":"string","const":"url"},"name":{"type":"string","minLength":1,"maxLength":255},"url":{"type":"string","format":"uri"},"tools":{"type":"object","properties":{"include":{"default":[],"maxItems":200,"type":"array","items":{"type":"string","minLength":1}},"exclude":{"default":[],"maxItems":200,"type":"array","items":{"type":"string","minLength":1}}}}},"required":["name","url"]},"description":"Declared remote MCP server references, including tool filters; runtime authentication fields are never returned"},"hooks":{"$schema":"http://json-schema.org/draft-07/schema#","maxItems":20,"type":"array","items":{"type":"object","properties":{"event":{"type":"string","enum":["pre_session_start","session_start","user_prompt_submit","pre_tool_use","post_tool_use","stop","session_end"]},"command":{"type":"string","minLength":1,"maxLength":4000},"matcher":{"type":"string","minLength":1,"maxLength":255},"timeout_s":{"type":"integer","minimum":1,"maximum":600}},"required":["event","command"],"additionalProperties":false},"description":"Shell commands run in the session's pod at lifecycle events"},"metadata":{"type":"object","description":"Your key-merged client metadata"},"environmentId":{"type":["string","null"],"description":"The environment sessions of this agent boot in when their create names none; ahead of the workspace default"},"vaultId":{"type":["string","null"],"description":"The vault every session of this agent carries, after the vaults its create names and ahead of the workspace default"},"defaultSessionId":{"type":["string","null"],"description":"The session conversation verbs target when addressed by agent id"},"universe":{"type":"string","description":"Resolved universe slug"}}},"Session":{"type":"object","properties":{"id":{"type":"string","description":"sess_… identifier"},"agentId":{"type":["string","null"],"description":"The agent id (agent_…)"},"title":{"type":["string","null"]},"status":{"type":"string","enum":["provisioning","idle","running","terminated"],"description":"provisioning = the sandbox is booting or installing the environment's packages (a turn sent meanwhile waits for it); running = a turn is in flight; terminated = archived or the last runtime was destroyed. Use archived for the durable archive receipt"},"archived":{"type":"boolean","description":"True only after this Session's archive mark was durably written; false for an active Session whose runtime was destroyed"},"agentType":{"type":"string"},"llm":{"type":"string","description":"The model this session runs on (PATCH to change; the agent's model is unchanged)"},"harnessVersion":{"type":"string","description":"Harness release the session runs: the one its serving pod booted, the restored checkpoint's for a native-fork handoff, the agent's pin for ACP harnesses, otherwise the current release"},"reasoningEffort":{"type":["string","null"],"description":"The model-compatible effort resolved from the session pin, then agent pin. Constrained models use an allowed fallback; no-setting models return null. Unpinned unconstrained models return null for the harness default."},"subscriptionApiFallback":{"type":"boolean","description":"Opt-in to paid API continuation after all subscription accounts exhaust, preserving the same supported explicit model and wallet/budget gates"},"modelBilling":{"type":"string","enum":["platform","account"],"description":"Who pays for model calls: platform wallet or the user's connected subscription"},"idleTimeoutSeconds":{"type":["integer","null"],"description":"Seconds the session's machine stays awake after a turn ends before it is paused; null = the platform default of 60. Set it when people use apps on the session's exposed ports after the agent finishes"},"default":{"type":"boolean","description":"Is this the agent's default session"},"payer":{"type":"object","description":"Who pays for it, decided once when it was created and never changed. Present only when a payer was recorded, which happens in a team workspace where workspace wallets are on; absent means its owner's own balance pays.","required":["type"],"properties":{"type":{"type":"string","enum":["workspace","personal"],"description":"`workspace`: the team workspace's own wallet. `personal`: the balance of the person who started it."},"workspace":{"type":"object","description":"The paying workspace; only with type workspace","properties":{"slug":{"type":"string"},"name":{"type":"string"}}}}},"metadata":{"type":"object"},"budget":{"type":["object","null"],"description":"Hard spend cap, or null when the session has none. A reached budget pauses the session (402 budget_reached on new work) until the cap is raised above consumed_cost or removed — removal is one-way.","properties":{"max_list_cost":{"$ref":"#/components/schemas/MonetaryAmount"},"consumed_cost":{"$ref":"#/components/schemas/MonetaryAmount"},"reached":{"type":"boolean"},"reached_at":{"type":["string","null"],"description":"ISO 8601"}}},"resources":{"type":"array","items":{"$ref":"#/components/schemas/SessionResource"},"description":"The files, GitHub repositories, and read-only memory stores mounted into the session, oldest first"},"workspaceDefaults":{"type":["object","null"],"description":"What the session started with because its workspace made it a default; everything else it carries was named at creation. Null when it took nothing.","required":["environmentId","vaultIds","mountPaths","skillIds"],"properties":{"environmentId":{"type":["string","null"],"description":"The workspace's default environment, when the session named none"},"vaultIds":{"type":"array","items":{"type":"string"},"description":"The workspace's default vault, when it holds a secret"},"mountPaths":{"type":"array","items":{"type":"string"},"description":"Where each always-available file was mounted"},"skillIds":{"type":"array","items":{"type":"string"},"description":"The always-available skills"}}},"hostedBySeller":{"type":"object","description":"Present only when the session runs on its agent's maker's own server instead of a sandbox: what is sent to the session goes to this host. `agentType` and `llm` then name a stand-in that never runs.","required":["host"],"properties":{"host":{"type":"string"}}},"attachments":{"type":"array","description":"Everything the session started with: its environment, vaults, mounted files and memory stores, and the workspace's always-available skills. The skills of the session's agent are on the agent and are not repeated here.","items":{"type":"object","required":["type","id","mountPath","source"],"properties":{"type":{"type":"string","enum":["environment","vault","file","skill","memory_store"]},"id":{"type":"string","description":"The id of the environment, vault, file, skill or memory store"},"mountPath":{"type":["string","null"],"description":"Where a file or memory store is mounted; null for the other types"},"source":{"type":"string","enum":["default","explicit"],"description":"default = the workspace supplied it; explicit = it was named when the session was created. A memory store on a session created before 2026-10-06 reads as explicit"}}}},"createdAt":{"type":"string","description":"ISO 8601"}}},"Routine":{"type":"object","description":"Scheduled agent execution: initial_events + a target (new_session per fire, or an existing session) bound to a cron schedule. Fires record routine runs.","properties":{"id":{"type":"string","description":"rtn_… identifier"},"name":{"type":"string"},"description":{"type":["string","null"]},"metadata":{"type":"object"},"target":{"type":"object","description":"{type:\"new_session\", agent, environment_id?, vault_ids?} — a fresh session per fire (CMA parity) · {type:\"session\", session_id} — a turn into the existing session every fire (busy target skips with session_busy_error)"},"initial_events":{"type":"array","items":{"type":"object"}},"schedule":{"type":["object","null"],"description":"5-field POSIX cron + IANA timezone, wall-clock matching, minute granularity; null = manual-run only","properties":{"type":{"type":"string","enum":["cron"]},"expression":{"type":"string"},"timezone":{"type":"string"},"last_run_at":{"type":["string","null"]},"upcoming_runs_at":{"type":"array","items":{"type":"string"},"description":"≤5 upcoming fire times; empty once archived"}}},"budget":{"type":["object","null"],"description":"Per-run cap (RFC-0080 shape): copied onto each new session (mode new_session) or granted as a per-fire delta allowance consumed+budget (mode session). Clearable."},"status":{"type":"string","enum":["active","paused"]},"paused_reason":{"type":["object","null"],"description":"{type:\"manual\"} | {type:\"error\", error:{type}} — non-null exactly when paused"},"archived_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}}},"RoutineRun":{"type":"object","description":"One fire attempt. Exactly one of session_id / error is non-null.","properties":{"id":{"type":"string","description":"rrun_… identifier"},"routine_id":{"type":"string"},"trigger_context":{"type":"object","description":"{type:\"schedule\", scheduled_at} | {type:\"manual\"}"},"session_id":{"type":["string","null"]},"error":{"type":["object","null"],"description":"{type, message}. Types: agent_archived_error · agent_not_found_error · session_archived_error · session_not_found_error · session_busy_error · environment_archived_error · environment_not_found_error · vault_not_found_error · insufficient_credits_error · rate_limited_error · run_rejected_error · unknown_error. Unrecoverable types auto-pause the routine; transient ones (credits, rate limit, busy) leave it active for the next occurrence. precheck_unchanged is not a failure: the scheduled fire was skipped because the routine's precheck URL returned the same content as at the last run; no session started, the routine stays active and no routine_run webhook is sent."},"agent":{"type":"object","description":"Resolved agent reference at fire time"},"created_at":{"type":"string"}}},"WebhookEndpoint":{"type":"object","description":"Outbound webhook endpoint. Deliveries carry x-asteroids-event/-delivery/-timestamp/-signature (v1=hmac-sha256(secret, \"<ts>.<body>\")), retry 3× (0s/5s/30s), and sustained failure disables (PATCH status:active re-enables). Payloads are thin {id, type, created_at, data:{type, id}} — fetch the resource, dedupe on the event id.","properties":{"id":{"type":"string","description":"whep_… identifier"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","disabled"]},"failure_count":{"type":"integer"},"created_at":{"type":"string"},"secret":{"type":"string","description":"whsec_… — present ONLY in the create response"}}},"MonetaryAmount":{"type":"object","description":"Whole US cents as an integer decimal string — \"125\" is $1.25","properties":{"amount":{"type":"string"},"currency":{"type":"string","enum":["USD"]}}},"Event":{"type":"object","description":"One session event — identical on the stream and in history. Core fields below; the payload varies by type (agent.message carries messageId/parts/text; agent.reasoning/tool_use/tool_result carry part; session.status_idle carries stop_reason; session.error carries error; user.interrupt carries by).","required":["id","type","sessionId"],"additionalProperties":true,"properties":{"id":{"type":"string","description":"Stable event id — the dedupe key across stream ∪ events"},"type":{"type":"string","description":"user.message · system.message (both history only — never on the live stream; they carry `content`) · agent.message · agent.reasoning · agent.tool_use · agent.tool_result · agent.status · user.interrupt · session.status_running · session.status_idle · session.error · session.status_terminated · session.deleted"},"sessionId":{"type":"string"},"agentId":{"type":["string","null"],"description":"The agent id (agent_…)"},"at":{"type":"string","description":"ISO 8601"},"messageId":{"type":"string","description":"agent.message"},"parts":{"type":"array","items":{"$ref":"#/components/schemas/MessagePart"},"description":"agent.message"},"text":{"type":"string","description":"agent.message — parts flattened to plain text"},"content":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"user.message / system.message — the CMA content blocks as sent (text · image · document); every image/document source is a `file` source naming a per-session copy readable through GET /files/{file_id}/content"},"part":{"$ref":"#/components/schemas/MessagePart","description":"reasoning / tool_use / tool_result / status events"},"stop_reason":{"type":"object","description":"session.status_idle — discriminate on type; never break on bare idle","properties":{"type":{"type":"string","description":"\"end_turn\" (also after an interrupt) | \"retries_exhausted\" (preceded by an exhausted engine error) | \"provider_lost\" (confirmed runtime Pod loss, preceded by an exhausted session.error) | \"budget_reached\"; more reserved"}}},"error":{"type":"object","description":"session.error — the stream stays open; a session.status_idle follows once the turn is over","properties":{"type":{"type":"string","description":"e.g. \"pod_unavailable\""},"message":{"type":"string"},"retry_status":{"type":"string","description":"\"retrying\" (the turn continues) | \"exhausted\" (the turn is over)"}}},"by":{"type":"string","description":"user.interrupt — who requested the interrupt"},"mode":{"type":"string","enum":["save"],"description":"user.interrupt — present on a save interrupt: the run was asked to save its work and end itself"},"deadline_at":{"type":"string","format":"date-time","description":"user.interrupt with mode save — when the run is stopped if it has not ended by then"},"cause":{"type":"string","enum":["save_timeout"],"description":"user.interrupt — present when the platform stopped a run whose save grace window ran out"},"actor":{"type":"object","description":"user.message only, in history and in the send echo: who sent it, present only when that was not the session's owner","properties":{"id":{"type":"string"},"name":{"type":["string","null"]}}}}},"EventsPage":{"type":"object","required":["events","cursor","hasMore"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/Event"},"description":"Oldest-first"},"cursor":{"type":["string","null"],"description":"Pass back as ?cursor= for the next page; null when the session has no events"},"hasMore":{"type":"boolean"}}},"PromptUpdateResult":{"type":"object","properties":{"version":{"type":"integer"},"unchanged":{"type":"boolean","description":"Content identical to the active version"}}},"PromptVersion":{"type":"object","properties":{"version":{"type":"integer"},"note":{"type":["string","null"]},"createdAt":{"type":"string"},"active":{"type":"boolean"},"content":{"type":"string"}}},"SecretKey":{"type":"object","description":"Key names only — values never leave the platform.","properties":{"key":{"type":"string"},"description":{"type":"string"}}},"ModelSubscription":{"type":"object","description":"A connected consumer AI subscription (Claude Pro/Max, ChatGPT, Cursor, Grok or Muse plan) powering eligible agents at $0 model usage. The credential itself is write-only.","properties":{"provider":{"type":"string","enum":["anthropic","openai","cursor","xai","meta"]},"accountId":{"type":"string","description":"Additional account identifier; omitted for the legacy provider account"},"label":{"type":"string"},"status":{"type":"string","enum":["connected","needs_reconnect"]},"expiresAt":{"type":["string","null"]},"lastUsedAt":{"type":["string","null"]},"useForNewAgents":{"type":"boolean"},"createdAt":{"type":"string"},"agents":{"type":"array","description":"Agents in this universe running on the subscription","items":{"type":"object","properties":{"id":{"type":"string"},"agentId":{"type":["string","null"]},"name":{"type":"string"}}}}}},"Ok":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},"InterruptResult":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["interrupting","no_turn"],"description":"no_turn = nothing in flight; otherwise user.interrupt echoes on the stream and the pod's session.status_idle follows"}}},"Skill":{"type":"object","required":["id","displayName","latestRevisionId","attachByDefault","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"displayName":{"type":"string"},"latestRevisionId":{"type":["string","null"],"description":"What `latest` references resolve to."},"attachByDefault":{"type":"boolean","description":"Whether every new session in the workspace starts with this skill's latest revision."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"SkillRevision":{"type":"object","required":["id","skillId","name","description","files","createdAt"],"properties":{"id":{"type":"string"},"skillId":{"type":"string"},"name":{"type":"string","description":"Frontmatter name — the skill's identity name."},"description":{"type":"string"},"files":{"type":"array","items":{"type":"object","required":["path","size","sha256","executable"],"properties":{"path":{"type":"string"},"size":{"type":"integer"},"sha256":{"type":"string"},"executable":{"type":"boolean"}}}},"createdAt":{"type":"string","format":"date-time"}}},"ChannelMessagePart":{"oneOf":[{"type":"object","required":["type","file_id"],"properties":{"type":{"const":"file"},"file_id":{"type":"string","pattern":"^file_[A-Za-z0-9_-]{1,128}$","description":"A visible, unexpired Files API upload or session output; requires capabilities.files."}}},{"type":"object","required":["type","text"],"properties":{"type":{"const":"text"},"text":{"type":"string"}}},{"type":"object","required":["type","text"],"properties":{"type":{"const":"markdown"},"text":{"type":"string"}}},{"type":"object","required":["type","platform","payload"],"properties":{"type":{"const":"raw"},"platform":{"type":"string"},"payload":{"type":"string","description":"Platform-native payload, JSON-encoded"}}}]},"ChannelClaim":{"type":"object","required":["author_id","thread_id"],"properties":{"author_id":{"type":"string","minLength":1,"description":"Verified author of the current LINK claim or administrator-attested adoption; independent of the current message speaker."},"thread_id":{"type":"string","minLength":1,"description":"SDK thread recorded by that claim, scoped to this connection and app."}},"description":"Service-owned connection claim. Never derived from caller metadata. Absent for unclaimed connections and loopback. Consumers must validate app/platform and must not substitute the current group speaker when absent."},"ChannelMessageReceived":{"type":"object","required":["id","type","createdAt","data"],"properties":{"id":{"type":"string"},"type":{"const":"message.received"},"createdAt":{"type":"string","format":"date-time"},"data":{"type":"object","required":["connection_id","app_id","thread_id","message_id","text","author","conversation","metadata"],"properties":{"connection_id":{"type":"string"},"app_id":{"type":["string","null"],"description":"Persisted channel app identity."},"thread_id":{"type":"string"},"message_id":{"type":"string"},"text":{"type":"string"},"author":{"type":"object","properties":{"user_id":{"type":"string"},"user_name":{"type":"string"}}},"conversation":{"type":"object","properties":{"channel_id":{"type":"string"},"is_dm":{"type":"boolean"}}},"metadata":{"type":"object","additionalProperties":true,"description":"Current caller-authored connection metadata, not identity authority."},"claim":{"$ref":"#/components/schemas/ChannelClaim"},"attachments":{"type":"array","items":{"type":"object"}}}}},"description":"HMAC-signed message event delivered to the configured webhook. The optional claim supports recovery when channel.connected was missed without confusing the claimant with a later group speaker."},"CreateChannelApp":{"type":"object","required":["platform","label","credentials"],"properties":{"platform":{"type":"string","enum":["telegram","slack","discord","whatsapp","imessage","email","teams","x","lark","buzz","gchat","line"]},"label":{"type":"string","maxLength":120},"credentials":{"type":"object","additionalProperties":{"type":"string"},"description":"Write-only. Required keys per platform — telegram: bot_token · discord: bot_token · slack: bot_token, signing_secret · whatsapp: access_token, phone_number_id, app_secret · email (requires EMAIL_CHANNEL_ENABLED): region, access_key, secret_key, from_address, sns_topic_arn; optional from_name, inbound_address, allow_subaddressing, reply_to_sender_only (string true/false); optional s3_bucket, s3_prefix (nonempty, ends /), s3_bucket_owner (12 digits), all three together for S3 receiving with the same region/key pair · teams (when enabled; app creation and credential rotation return 501 coming_soon when disabled): app_id (Azure Application client ID), app_password (client secret); optional app_tenant_id (Directory ID for single-tenant bots, omit for multi-tenant). Credentials are validated against Azure AD on creation. The API returns a webhook_url to paste into Azure Bot Configuration → Messaging Endpoint. Connection returns PENDING and a LINK code to send to the bot. Each conversation can bind to its own session. · imessage (coming soon — answers 501 coming_soon today): api_key, phone_number, webhook_secret · x: consumer_secret + either user_access_token (Group A, OAuth 2.0 Bearer) or client_id + refresh_token (Group B, OAuth 2.0 managed refresh). Exactly one group must be supplied. · lark: app_id, app_secret, verification_token (optional encrypt_key, domain: lark|feishu, app_mode: self-built|store, app_ticket for migration) · buzz: private_key, auth_tag · gchat: service_account_json, project_number · line: channel_access_token, channel_secret (requires LINE_CHANNEL_ENABLED; setup returns manual webhook instructions)"}}},"PatchChannelApp":{"type":"object","properties":{"retry_registration":{"type":"boolean","description":"Retry saved X verification without resubmitting credentials; mutually exclusive with credentials"},"label":{"type":"string","maxLength":120},"credentials":{"type":"object","additionalProperties":{"type":"string"},"description":"Full replacement bag; rotation re-runs the platform registration"}}},"ChannelApp":{"type":"object","properties":{"verification_error":{"type":"string","description":"Non-secret explanation when X verification remains pending"},"verification_retryable":{"type":"boolean","description":"Present for pending X verification. False means the saved refresh attempt cannot be replayed; replace credentials with a fresh OAuth grant."},"id":{"type":"string"},"platform":{"type":"string","enum":["telegram","slack","discord","whatsapp","imessage","email","teams","x","lark","buzz","gchat","line"]},"label":{"type":"string"},"status":{"type":"string"},"credential_keys":{"type":"array","items":{"type":"string"},"description":"Key names only — values are write-only"},"created_at":{"type":"string","format":"date-time"},"setup":{"type":"object","additionalProperties":{"type":"string"},"description":"Steps the platform cannot automate (per-app webhook_url / verify_token / events_url / invite_url)"}}},"CreateChannelConnection":{"type":"object","required":["platform"],"properties":{"platform":{"type":"string","enum":["telegram","slack","discord","whatsapp","imessage","email","teams","x","lark","buzz","gchat","line","loopback"]},"label":{"type":"string","maxLength":120},"metadata":{"type":"object","description":"Echoed on channel.connected and the callback redirect"},"destination":{"type":"object","properties":{"session":{"type":"string"},"webhook":{"type":"string"}},"description":"Pre-bind to exactly one owned session or webhook endpoint when the surface is claimed"},"app":{"type":"string","description":"BYO ChannelApp id — the connect ceremony runs on your bot/number"},"adopt":{"type":"object","required":["thread_id","author_id"],"additionalProperties":false,"properties":{"thread_id":{"type":"string","minLength":1,"maxLength":8192},"author_id":{"type":"string","minLength":1,"maxLength":1024},"tenant_key":{"type":"string","minLength":1,"maxLength":256,"description":"Required only for Lark Store adoption; provider app and chat state must confirm this organization."}},"description":"Admin-scope migration of the app owner's previously verified conversation. Requires an owned active app, an app-scoped thread ID and destination. The caller attests the existing sender binding and consent; no LINK ceremony or provider message is performed. Exact replay reuses the connection; changed sender, metadata, destination or a disconnected record returns 409. Cannot combine with callback_url or invite_user."},"invite_user":{"type":"string","description":"Slack only: user id to invite into the created channel"},"callback_url":{"type":"string","description":"Link-flow platforms only: the hosted connect page redirects here after the claim with connection_id, status, and metadata query params"}}},"ChannelConnection":{"type":"object","properties":{"id":{"type":"string"},"platform":{"type":"string"},"channel_id":{"type":"string","nullable":true},"thread_id":{"type":"string","description":"Present after administrative adoption; the existing app-scoped reply address"},"label":{"type":"string"},"status":{"type":"string","enum":["PENDING","CONNECTED","DISCONNECTED"]},"bound_session":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"label":{"type":"string"}}},"created_at":{"type":"string","format":"date-time"},"connect":{"type":"object","description":"PENDING only: open url; X and webhook-based Slack/Discord use a hosted page, phone-based flows include phone + code, and Lark includes app_id and a code to send to the bot.","properties":{"url":{"type":"string"},"phone":{"type":"string"},"app_id":{"type":"string","description":"Lark app ID used to open the bot"},"code":{"type":"string"},"expires_at":{"type":"string","format":"date-time"}}}}},"CreateChannelBinding":{"type":"object","required":["connection_id","thread_id","destination"],"properties":{"connection_id":{"type":"string"},"thread_id":{"type":"string","description":"The one thread this rule routes. Connection-level routing is a single slot — set it via PUT /connections/{id}/binding"},"destination":{"type":"object","description":"Exactly one of webhook (endpoint id) or session (session id)","properties":{"webhook":{"type":"string"},"session":{"type":"string"}}},"route_key":{"type":"string","maxLength":60}}},"ChannelBinding":{"type":"object","properties":{"id":{"type":"string"},"connection_id":{"type":"string"},"thread_id":{"type":"string","nullable":true},"destination":{"type":"object","description":"Exactly one of webhook (endpoint id) or session (session id)","properties":{"webhook":{"type":"string"},"session":{"type":"string"}}},"is_default":{"type":"boolean"},"status":{"type":"string"},"route_key":{"type":"string"}}},"ChannelIdentity":{"type":"object","description":"A person in a connected chat, linked to the account their messages there run as.","properties":{"id":{"type":"string"},"platform":{"type":"string","enum":["telegram","slack","discord","whatsapp","imessage","email","teams","x","lark","buzz","gchat","line"]},"external_user_id":{"type":"string","description":"The person's id on that platform"},"display_name":{"type":"string","nullable":true},"linked_at":{"type":"string","format":"date-time","nullable":true}}},"CreateChannelWebhook":{"type":"object","required":["url"],"properties":{"url":{"type":"string","description":"https (http allowed for localhost only)"},"events":{"type":"array","items":{"type":"string"},"description":"Default [\"message.received\"]"}}},"ChannelWebhookEndpoint":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"status":{"type":"string"},"secret":{"type":"string","description":"whsec_ HMAC secret — returned on create only"}}},"PostChannelMessage":{"type":"object","required":["parts"],"properties":{"parts":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/ChannelMessagePart"}},"email":{"type":"object","additionalProperties":false,"description":"SES-only headers. The authorized thread owns the recipient; this object cannot change To.","properties":{"subject":{"type":"string","minLength":1,"maxLength":200,"pattern":"^[^\\r\\n]+$"},"reply_to":{"type":"string","format":"email"}}},"idempotency_key":{"type":"string","minLength":1,"maxLength":200,"description":"Durable replay key scoped to the persisted owner, connection and thread, independent of bearer token scope. Same-content replays return the accepted receipt even after disconnect; changed content or an unconfirmed send returns 409 without resending."},"done":{"type":"boolean","description":"Resolves the working marker as successful; cannot be true with failed"},"failed":{"type":"boolean","description":"Resolves the working marker as failed; cannot be true with done"}}},"PostChannelDelivery":{"type":"object","required":["destination","parts"],"properties":{"destination":{"type":"object","description":"Exactly one of webhook (endpoint id) or session (session id)","properties":{"webhook":{"type":"string"},"session":{"type":"string"}}},"parts":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/ChannelMessagePart"}},"done":{"type":"boolean","description":"Resolves each working marker as successful; cannot be true with failed"},"failed":{"type":"boolean","description":"Resolves each working marker as failed; cannot be true with done"}}},"ChannelDevInbound":{"type":"object","required":["text"],"properties":{"text":{"type":"string"},"thread":{"type":"string","description":"Thread key within the connection; default \"main\""},"id":{"type":"string","description":"Message id to attribute it to; default a generated one"},"author":{"type":"object","required":["user_id"],"properties":{"user_id":{"type":"string"},"user_name":{"type":"string"}}},"mention":{"type":"boolean","description":"Whether it reads as a mention of the bot"}}},"ChannelCapabilities":{"type":"object","properties":{"connection_id":{"type":"string"},"platform":{"type":"string"},"capabilities":{"type":"object","additionalProperties":{"type":"boolean"},"description":"threads · reactions · markers · proactive · markdown · modals · ephemeral · streaming · files"}}},"File":{"type":"object","required":["type","id","created_at","filename","mime_type","size_bytes","downloadable","attach_by_default","expires_at"],"properties":{"type":{"type":"string","enum":["file"]},"id":{"type":"string","description":"file_…"},"created_at":{"type":"string","format":"date-time"},"filename":{"type":"string"},"mime_type":{"type":"string"},"size_bytes":{"type":"integer"},"downloadable":{"type":"boolean","description":"true for image uploads (readable within the workspace) and for the per-session copies minted when a file rides a message; false for other uploads (write-once)"},"attach_by_default":{"type":"boolean","description":"Whether every new session in the workspace starts with a read-only copy under /workspace/shared/"},"expires_at":{"type":["string","null"],"format":"date-time"}}},"FileList":{"type":"object","required":["data","next_page"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/File"},"description":"Newest first"},"next_page":{"type":["string","null"],"description":"Pass back as ?page= for the next page"}}},"FileDeleted":{"type":"object","required":["type","id"],"properties":{"type":{"type":"string","enum":["file_deleted"]},"id":{"type":"string"}}},"MemoryStore":{"type":"object","required":["id","object","name","description","attach_by_default","created_at","updated_at","archived_at"],"properties":{"id":{"type":"string","description":"memstore_…"},"object":{"type":"string","enum":["memory_store"]},"name":{"type":"string"},"description":{"type":"string"},"attach_by_default":{"type":"string","enum":["none","read_only"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"archived_at":{"type":["string","null"],"format":"date-time"}}},"MemoryCompact":{"type":"object","description":"Memory without content — returned in list responses.","required":["id","type","object","memory_store_id","path","content_sha256","content_bytes","created_at","updated_at"],"properties":{"id":{"type":"string","description":"mem_…"},"type":{"type":"string","enum":["memory"],"description":"Discriminator for the memories list union."},"object":{"type":"string","enum":["memory"]},"memory_store_id":{"type":"string"},"path":{"type":"string","description":"Absolute path starting with /"},"content_sha256":{"type":"string"},"content_bytes":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"MemoryFull":{"type":"object","description":"Memory with content — returned by single-get, create, and update responses.","required":["id","object","memory_store_id","path","content","content_sha256","content_bytes","created_at","updated_at"],"properties":{"id":{"type":"string","description":"mem_…"},"object":{"type":"string","enum":["memory"]},"memory_store_id":{"type":"string"},"path":{"type":"string","description":"Absolute path starting with /"},"content":{"type":"string"},"content_sha256":{"type":"string"},"content_bytes":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"MemoryVersion":{"type":"object","required":["id","object","memory_store_id","memory_id","path","content","content_sha256","operation","actor_type","actor_id","redacted_at","created_at"],"properties":{"id":{"type":"string","description":"memver_…"},"object":{"type":"string","enum":["memory_version"]},"memory_store_id":{"type":"string"},"memory_id":{"type":"string"},"path":{"type":"string"},"content":{"type":["string","null"],"description":"null when redacted"},"content_sha256":{"type":["string","null"]},"operation":{"type":"string","enum":["create","update","delete"]},"actor_type":{"type":"string","enum":["user","session"]},"actor_id":{"type":"string"},"redacted_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"GoalCriterion":{"type":"object","required":["id","text"],"properties":{"id":{"type":"string","description":"Stable within the goal, e.g. c1"},"text":{"type":"string"},"command":{"type":"string","description":"Present when a shell command decides this criterion: it runs in the session's workspace after each iteration, and exit 0 means met. The grader cannot overturn it."}}},"GoalEvaluation":{"type":"object","required":["result","explanation","criteria","iteration","at"],"description":"The grader's read of the most recent iteration.","properties":{"result":{"type":"string","enum":["satisfied","needs_revision","failed"]},"explanation":{"type":"string"},"criteria":{"type":"array","items":{"type":"object","required":["id","met","reason"],"properties":{"id":{"type":"string"},"met":{"type":"boolean"},"reason":{"type":"string"},"judged_by":{"type":"string","enum":["grader","command"],"description":"What decided this criterion on this iteration"}}}},"iteration":{"type":"integer"},"at":{"type":"string","format":"date-time"}}},"Goal":{"type":"object","required":["id","session","objective","criteria","criteria_source","status","stop_reason","iteration","max_iterations","max_spend","consumed_spend","max_tokens","consumed_tokens","deadline_at","last_evaluation","created_at","updated_at","completed_at"],"properties":{"id":{"type":"string","description":"goal_…"},"session":{"type":"string","description":"sess_…"},"objective":{"type":"string"},"criteria":{"type":"array","items":{"$ref":"#/components/schemas/GoalCriterion"}},"criteria_source":{"type":"string","enum":["user","derived"],"description":"Whether the caller supplied the criteria or the platform derived them from the objective"},"status":{"type":"string","enum":["active","paused","completed","stopped"]},"stop_reason":{"type":["string","null"],"enum":["failed","max_iterations","spend_budget","token_budget","time_budget","no_progress","cleared","session_ended",null],"description":"Why a stopped goal stopped; null in every other status"},"iteration":{"type":"integer","description":"Self-started turns taken so far"},"max_iterations":{"type":"integer"},"max_spend":{"oneOf":[{"type":"object","properties":{"amount":{"type":"string"},"currency":{"type":"string","enum":["USD"]}}},{"type":"null"}]},"consumed_spend":{"type":"object","description":"What this session has spent since the goal started","properties":{"amount":{"type":"string"},"currency":{"type":"string","enum":["USD"]}}},"max_tokens":{"type":["integer","null"],"description":"Token ceiling for this goal; null = none"},"consumed_tokens":{"type":"integer","description":"Uncached input plus output tokens over the session's metered model calls since the goal started, grading included. Calls on the session's own model subscription are not metered and not counted."},"deadline_at":{"type":["string","null"],"format":"date-time"},"last_evaluation":{"oneOf":[{"$ref":"#/components/schemas/GoalEvaluation"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"}}},"SessionResource":{"description":"A file, GitHub repository, or memory-store snapshot mounted read-only into the session. A read_write memory-store grant also permits updates through the session-scoped Agent API. Workspace paths are under /workspace; memory paths are under /mnt/memory. A file resource's `file_id` is the per-session copy (listed under GET /files?scope_id=). Repository tokens and memory contents are never echoed here.","oneOf":[{"type":"object","required":["type","id","file_id","mount_path","created_at","updated_at"],"properties":{"type":{"type":"string","enum":["file"]},"id":{"type":"string","description":"sesrsc_…"},"file_id":{"type":"string","description":"The per-session copy (file_…), read-only at mount_path"},"mount_path":{"type":"string","description":"Absolute, under /workspace"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},{"type":"object","required":["type","id","url","mount_path","created_at","updated_at"],"properties":{"type":{"type":"string","enum":["github_repository"]},"id":{"type":"string","description":"sesrsc_…"},"url":{"type":"string","description":"https://github.com/{owner}/{repo}"},"mount_path":{"type":"string","description":"Absolute, under /workspace; the clone's root"},"checkout":{"type":"object","description":"{type:\"branch\", name} or {type:\"commit\", sha}; absent = the default branch","properties":{"type":{"type":"string","enum":["branch","commit"]},"name":{"type":"string"},"sha":{"type":"string"}}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},{"type":"object","required":["type","id","memory_store_id","mount_path","access","created_at","updated_at"],"properties":{"type":{"type":"string","enum":["memory_store"]},"id":{"type":"string","description":"smsr_…"},"memory_store_id":{"type":"string","description":"memstore_…"},"mount_path":{"type":"string","description":"Absolute, under /mnt/memory"},"access":{"type":"string","enum":["read_only","read_write"]},"instructions":{"type":"string","description":"Optional per-session guidance"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}]},"SessionResourceList":{"type":"object","required":["data","next_page"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SessionResource"},"description":"Oldest first"},"next_page":{"type":["string","null"],"description":"Pass back as ?page= for the next page; null when `limit` was omitted or the list ended"}}},"SessionResourceDeleted":{"type":"object","required":["type","id"],"properties":{"type":{"type":"string","enum":["session_resource_deleted"]},"id":{"type":"string"}}},"BrowserTask":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"task":{"type":"string","minLength":12,"maxLength":16000},"startUrl":{"type":"string","format":"uri"},"viewport":{"type":"object","properties":{"width":{"type":"integer","minimum":640,"maximum":1920},"height":{"type":"integer","minimum":480,"maximum":1440}},"required":["width","height"],"additionalProperties":false},"verification":{"type":"object","properties":{"kind":{"type":"string","const":"google-flights"},"origin":{"type":"string","minLength":1,"maxLength":120},"destination":{"type":"string","minLength":1,"maxLength":120},"departureDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"returnDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"passengers":{"type":"integer","minimum":1,"maximum":9},"cabin":{"type":"string","enum":["economy","premium-economy","business","first"]}},"required":["kind","origin","destination","departureDate","passengers","cabin"],"additionalProperties":false}},"required":["task","startUrl","viewport"],"additionalProperties":false},"SessionBrowser":{"type":"object","required":["id","status","viewerUrl","url","startedAt","expiresAt","endedAt","elapsedMs","actions","actionCount","verification","lastScreenshot","costs","cleanupPending"],"properties":{"id":{"type":"string"},"status":{"type":"string","enum":["preparing","running","completed","blocked","failed","stopped"]},"viewerUrl":{"type":"null","description":"Always null. Observation uses screenshots; interactive provider viewer links are never exposed."},"url":{"type":"string"},"startedAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"elapsedMs":{"type":"number"},"actionCount":{"type":"integer"},"progress":{"type":"string"},"claim":{"type":"string","description":"The agent's completion claim, separate from task verification."},"resolvedModel":{"type":"string","description":"Resolved Jev model reported by OpenRouter."},"error":{"type":"string"},"actions":{"type":"array","items":{"type":"object","required":["id","verb","detail","timestamp","status"],"properties":{"id":{"type":"string"},"verb":{"type":"string"},"detail":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"status":{"type":"string"}}}},"verification":{"type":"object","required":["status","checks"],"properties":{"status":{"type":"string","enum":["passed","failed","unverified"]},"checks":{"type":"array","items":{"type":"object","required":["label","status","detail"],"properties":{"label":{"type":"string"},"status":{"type":"string","enum":["passed","failed","unverified"]},"detail":{"type":"string"}}}}}},"lastScreenshot":{"type":["string","null"],"description":"Latest observed or final JPEG as a data URL when capture succeeded."},"lastScreenshotAt":{"type":["string","null"],"format":"date-time","description":"Time the latest screenshot was captured successfully."},"cleanupPending":{"type":"boolean","description":"A terminal browser may still be releasing provider resources; cleanup is retried durably."},"costs":{"type":"object","required":["decisionUsd","helperUsd","browserUsd","runtimeUsd","totalUsd","chargedUsd"],"properties":{"decisionUsd":{"type":"number"},"helperUsd":{"type":"number"},"browserUsd":{"type":"number"},"runtimeUsd":{"type":"number"},"totalUsd":{"type":"number","description":"Metered cost including waived usage."},"chargedUsd":{"type":"number","description":"Actual amount charged after billing waivers."}},"description":"Recorded billed USD, including the fixed Mercury text-entry helper. Receipts can arrive after completion."}}},"SessionUsage":{"type":"object","required":["session","totals","entries","cursor"],"properties":{"session":{"type":"string"},"totals":{"type":"object","description":"Summed over the whole session, not just this page. `durationComplete` is false while a turn is still running. `tokenCostsUsd` is only present when every model charge carried its original breakdown.","properties":{"listCostUsd":{"type":"number"},"billedCostUsd":{"type":"number"},"inputTokens":{"type":"integer"},"outputTokens":{"type":"integer"},"cachedInputTokens":{"type":"integer"},"cacheCreationTokens":{"type":"integer"},"modelBilledCostUsd":{"type":"number"},"runtimeCostUsd":{"type":"number"},"capabilityCallCostUsd":{"type":"number"},"connectorCallCostUsd":{"type":"number"},"turns":{"type":"integer"},"durationMs":{"type":"integer"},"durationComplete":{"type":"boolean"},"coveredBy":{"type":["string","null"],"enum":["subscription",null]},"tokenCostsUsd":{"type":["object","null"],"properties":{"input":{"type":"number"},"output":{"type":"number"},"cachedInput":{"type":"number"},"cacheCreation":{"type":"number"}}}}},"entries":{"type":"array","items":{"$ref":"#/components/schemas/SessionUsageEntry"}},"budget":{"type":["object","null"],"description":"The session's budget summary — the same shape as `budget` on Session — or null when it has none"},"cursor":{"type":["string","null"],"description":"Pass as ?cursor= for the next page; null on the last"}}},"SessionUsageEntry":{"type":"object","required":["kind","at","billedCostUsd","tokens"],"properties":{"kind":{"type":"string"},"at":{"type":"string","format":"date-time"},"listCostUsd":{"type":["number","null"]},"billedCostUsd":{"type":"number"},"coveredBy":{"type":["string","null"],"enum":["subscription",null],"description":"Why a metered turn was booked at $0, when that is known"},"model":{"type":["string","null"]},"provider":{"type":["string","null"]},"basis":{"type":["string","null"]},"durationMs":{"type":["integer","null"]},"interrupted":{"type":["boolean","null"]},"tokens":{"type":"object","properties":{"input":{"type":"integer"},"output":{"type":"integer"},"cachedInput":{"type":"integer"},"cacheCreation":{"type":"integer"}}}}},"SessionStudioRequest":{"type":"object","properties":{"port":{"type":"integer","minimum":1024,"maximum":65535,"description":"Omitted = the studio's default port"}}},"SessionStudio":{"type":"object","required":["url","port"],"properties":{"url":{"type":"string","description":"https://studio-<token>.agentsky.dev — the token is the whole address"},"port":{"type":"integer"}}},"SessionPortRequest":{"type":"object","properties":{"visibility":{"type":"string","enum":["private","public"],"description":"Omitted = keep the stored value (private for a new port)"}}},"SessionPort":{"type":"object","required":["port","id","url","visibility","created_at"],"properties":{"port":{"type":"integer","description":"What the app listens on inside the pod"},"id":{"type":"string","description":"Names the origin; not a credential"},"url":{"type":"string","description":"https://app-<id>.agentsky.dev/ — stable for the port's life"},"visibility":{"type":"string","enum":["private","public"]},"created_at":{"type":"string","format":"date-time"}}},"SessionPortList":{"type":"object","required":["ports"],"properties":{"ports":{"type":"array","items":{"$ref":"#/components/schemas/SessionPort"}}}},"DesktopMachineRequest":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"What the person calls this Mac"}}},"DesktopMachine":{"type":"object","required":["id","name","online","last_seen_at","created_at"],"properties":{"id":{"type":"string","description":"mac_…"},"name":{"type":"string"},"online":{"type":"boolean","description":"The Mac app polled within the last minute"},"last_seen_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"DesktopMachineCreated":{"type":"object","required":["machine","connect_token"],"properties":{"machine":{"$ref":"#/components/schemas/DesktopMachine"},"connect_token":{"type":"string","description":"dmc_… — shown once; the Mac app's only credential, stored hashed"}}},"DesktopMachineList":{"type":"object","required":["machines"],"properties":{"machines":{"type":"array","items":{"$ref":"#/components/schemas/DesktopMachine"}}}},"DesktopMountRequest":{"type":"object","required":["root","label"],"properties":{"root":{"type":"string","description":"The folder's absolute path on that Mac"},"label":{"type":"string","description":"What the thread shows for it"}}},"DesktopMount":{"type":"object","required":["id","machine_id","root","label","mcp_url","created_at"],"properties":{"id":{"type":"string","description":"dmt_…"},"machine_id":{"type":"string"},"root":{"type":"string"},"label":{"type":"string"},"mcp_url":{"type":"string","description":"https://mac-<token>.agentsky.dev/mcp — put it in a spec's mcp_servers as a url server; the token is the credential"},"created_at":{"type":"string","format":"date-time"}}},"DesktopMountVerifyRequest":{"type":"object","required":["mcp_url"],"properties":{"mcp_url":{"type":"string","description":"The mount capability URL returned when the folder was selected"}}},"SessionPortGrantRequest":{"type":"object","properties":{"path":{"type":"string","description":"Where on the app to land after entering; a path on the port's origin, default /"}}},"SessionPortGrant":{"type":"object","required":["url","expires_at"],"properties":{"url":{"type":"string","description":"A private port: a single-use entry link, good for a minute; a public port: the plain address"},"expires_at":{"type":["string","null"],"format":"date-time"}}},"Environment":{"type":"object","required":["id","name","config","is_default","extends","created_at","updated_at"],"properties":{"id":{"type":"string","description":"env_…"},"name":{"type":"string"},"config":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"type":{"default":"cloud","type":"string","const":"cloud"},"packages":{"type":"object","properties":{"apt":{"default":[],"maxItems":32,"type":"array","items":{"type":"string","minLength":1,"maxLength":512}},"pip":{"default":[],"maxItems":32,"type":"array","items":{"type":"string","minLength":1,"maxLength":512}},"npm":{"default":[],"maxItems":32,"type":"array","items":{"type":"string","minLength":1,"maxLength":512}}}},"networking":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"unrestricted"}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"limited"},"allowed_hosts":{"default":[],"maxItems":32,"type":"array","items":{"type":"string","minLength":1,"maxLength":253,"pattern":"^(\\*\\.)?([a-z0-9]([a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?$"}},"allow_mcp_servers":{"default":false,"type":"boolean"},"allow_package_managers":{"default":false,"type":"boolean"}},"required":["type"]}]}},"description":"`packages` are installed into the image at build time — an environment is built when it is created and rebuilt when its config changes, so a session starting from it pays no install cost. `networking` is the egress policy its sessions run under; `limited` needs `allow_package_managers` when packages are declared, or the install could never succeed."},"is_default":{"type":"boolean","description":"Whether a new session that names no environment uses this one. At most one per workspace; setting it on one clears it on the others."},"extends":{"type":["string","null"],"description":"The env_… id of the parent environment this one extends, or null. Immutable after create. Child packages, tools.disabled and networking compose on the parent's at write time."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"EnvironmentList":{"type":"object","required":["environments"],"properties":{"environments":{"type":"array","items":{"$ref":"#/components/schemas/Environment"}}}},"CreateEnvironment":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"config":{"default":{"type":"cloud"},"type":"object","properties":{"type":{"default":"cloud","type":"string","const":"cloud"},"packages":{"type":"object","properties":{"apt":{"default":[],"maxItems":32,"type":"array","items":{"type":"string","minLength":1,"maxLength":512}},"pip":{"default":[],"maxItems":32,"type":"array","items":{"type":"string","minLength":1,"maxLength":512}},"npm":{"default":[],"maxItems":32,"type":"array","items":{"type":"string","minLength":1,"maxLength":512}}}},"networking":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"unrestricted"}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"limited"},"allowed_hosts":{"default":[],"maxItems":32,"type":"array","items":{"type":"string","minLength":1,"maxLength":253,"pattern":"^(\\*\\.)?([a-z0-9]([a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?$"}},"allow_mcp_servers":{"default":false,"type":"boolean"},"allow_package_managers":{"default":false,"type":"boolean"}},"required":["type"]}]}}},"extends":{"type":"string"}},"required":["name"]},"PatchEnvironment":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"config":{"type":"object","properties":{"type":{"default":"cloud","type":"string","const":"cloud"},"packages":{"type":"object","properties":{"apt":{"default":[],"maxItems":32,"type":"array","items":{"type":"string","minLength":1,"maxLength":512}},"pip":{"default":[],"maxItems":32,"type":"array","items":{"type":"string","minLength":1,"maxLength":512}},"npm":{"default":[],"maxItems":32,"type":"array","items":{"type":"string","minLength":1,"maxLength":512}}}},"networking":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"unrestricted"}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"limited"},"allowed_hosts":{"default":[],"maxItems":32,"type":"array","items":{"type":"string","minLength":1,"maxLength":253,"pattern":"^(\\*\\.)?([a-z0-9]([a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?$"}},"allow_mcp_servers":{"default":false,"type":"boolean"},"allow_package_managers":{"default":false,"type":"boolean"}},"required":["type"]}]}}}}},"PartnerHostname":{"type":"object","properties":{"hostname":{"type":"string"},"plane":{"type":"string","enum":["API","GATEWAY","APP","ACCOUNTS","STUDIO_POOL","STUDIO_WILDCARD"]},"ssl_status":{"type":"string"},"serving":{"type":"boolean","description":"Only a serving hostname counts toward going live."}}},"Partner":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["pending","active","suspended"]},"key_prefix":{"type":"string","nullable":true,"description":"Null until claimed."},"brand":{"type":"object","additionalProperties":{"type":"string"}},"brand_missing":{"type":"array","items":{"type":"string"},"description":"Brand fields still falling back to ours."},"rate_limit_per_min":{"type":"integer","nullable":true},"hostname_quota":{"type":"integer"},"hostnames":{"type":"array","items":{"$ref":"#/components/schemas/PartnerHostname"}}}},"PartnerState":{"type":"object","properties":{"state":{"type":"string","enum":["unapplied","waiting","rejected","setting_up","live","suspended"]},"next_action":{"type":"string","nullable":true,"description":"The one call that advances onboarding; null when nothing does."},"outstanding":{"type":"array","items":{"type":"string"}},"partner":{"allOf":[{"$ref":"#/components/schemas/Partner"}],"nullable":true}}},"ApplyForPartner":{"type":"object","required":["productName","intendedHost"],"properties":{"productName":{"type":"string","description":"What this partner's customers will call the product."},"intendedHost":{"type":"string","description":"Advisory at this stage; hostnames are claimed later."},"notes":{"type":"string"}}},"ClaimKeyPrefix":{"type":"object","required":["prefix"],"properties":{"prefix":{"type":"string","description":"2–8 lowercase letters or digits, starting with a letter."}}},"AddPartnerHostname":{"type":"object","required":["hostname","plane"],"properties":{"hostname":{"type":"string"},"plane":{"type":"string","enum":["API","GATEWAY","APP","ACCOUNTS","STUDIO_POOL"]}}},"PartnerSiteBrand":{"type":"object","required":["productName"],"description":"How the partner's product looks in a browser on its own hostnames.","properties":{"productName":{"type":"string","description":"The name in the tab and the navigation. Up to 60 characters."},"description":{"type":"string","description":"The line under the name in a search result or a share card. Up to 200 characters."},"logoUrl":{"type":"string","format":"uri","description":"https only."},"iconUrl":{"type":"string","format":"uri","description":"https only."},"shareImageUrl":{"type":"string","format":"uri","description":"https only."},"accountsOrigin":{"type":"string","format":"uri","description":"A bare https origin naming one of this partner's own hostnames that is serving sign-in."},"theme":{"type":"object","additionalProperties":{"type":"string"},"description":"Colours by token name."}}},"PartnerSite":{"type":"object","properties":{"brand":{"allOf":[{"$ref":"#/components/schemas/PartnerSiteBrand"}],"nullable":true},"helpers":{"description":"\"all\", or the handles agents in this partner's workspaces may hire.","oneOf":[{"type":"string","enum":["all"]},{"type":"array","items":{"type":"string"}}]},"agents":{"type":"array","items":{"type":"string"},"description":"The handles of this partner's own agents: the only ones its hostnames list."},"only_here":{"type":"array","items":{"type":"string"},"description":"Those of `agents` that are listed on this partner's hostnames and nowhere else. The rest also appear in the general catalog once approved."}}},"PartnerSiteInput":{"type":"object","properties":{"brand":{"allOf":[{"$ref":"#/components/schemas/PartnerSiteBrand"}],"nullable":true},"helpers":{"oneOf":[{"type":"string","enum":["all"]},{"type":"array","items":{"type":"string"},"maxItems":50}]},"agents":{"type":"array","items":{"type":"string"},"maxItems":50,"description":"Each must be a listing in a workspace this partner's owner owns."},"only_here":{"type":"array","items":{"type":"string"},"maxItems":50,"description":"Replaces the list whole. Each must be one of `agents`. Refused 422 while this partner's hostnames are not switched on."}}},"PartnerBrand":{"type":"object","required":["productName","requestIdHeader","spendGateHeader","spendGateMessage","billingUrl","docsUrl","supportUrl","frameAncestors"],"properties":{"productName":{"type":"string"},"requestIdHeader":{"type":"string","description":"Written into responses verbatim; must look like x-something."},"spendGateHeader":{"type":"string","description":"Must look like x-something."},"spendGateMessage":{"type":"string","description":"What this partner's customer reads when their balance is empty."},"billingUrl":{"type":"string","format":"uri"},"docsUrl":{"type":"string","format":"uri"},"supportUrl":{"type":"string","format":"uri"},"frameAncestors":{"type":"string","format":"uri","description":"A bare https origin naming one of this partner's own hostnames — it becomes the CSP on their customers' session pages."}}},"Vault":{"type":"object","required":["type","id","display_name","created_at","updated_at"],"properties":{"type":{"type":"string","enum":["vault"]},"id":{"type":"string","description":"vlt_…"},"display_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"VaultSecret":{"type":"object","description":"Metadata only — the secret value is never returned after it is written. `secret_name` is set for environment_variable secrets, `mcp_server_url` for the two MCP kinds.","required":["type","id","display_name","auth_type","status","created_at","updated_at"],"properties":{"type":{"type":"string","enum":["vault_secret"]},"id":{"type":"string","description":"vsec_…"},"display_name":{"type":"string"},"auth_type":{"type":"string","enum":["static_bearer","mcp_oauth","environment_variable"]},"mcp_server_url":{"type":"string"},"secret_name":{"type":"string","description":"The environment variable the pod sees"},"status":{"type":"string"},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"VaultList":{"type":"object","required":["vaults"],"properties":{"vaults":{"type":"array","items":{"$ref":"#/components/schemas/Vault"}}}},"VaultSecretList":{"type":"object","required":["secrets"],"properties":{"secrets":{"type":"array","items":{"$ref":"#/components/schemas/VaultSecret"}}}},"VaultSecretValidation":{"type":"object","description":"valid = the grant was exercised and the token renewed · invalid = the grant is dead, re-supply it · unknown = the endpoint was unreachable, retry.","required":["result","secret"],"properties":{"result":{"type":"string","enum":["valid","invalid","unknown"]},"detail":{"type":"string"},"secret":{"$ref":"#/components/schemas/VaultSecret"}}},"VaultSecretMove":{"type":"object","required":["dry_run","secrets"],"properties":{"dry_run":{"type":"boolean"},"secrets":{"type":"array","items":{"type":"object","required":["from","name","auth_type","outcome","source"],"properties":{"from":{"type":"string","description":"The vault it was in (vlt_…)"},"name":{"type":"string","description":"The environment variable name, or the display name of an MCP secret"},"auth_type":{"type":"string","enum":["static_bearer","mcp_oauth","environment_variable"]},"outcome":{"type":"string","enum":["moved","already","clash","blocked"]},"source":{"type":"string","enum":["removed","kept"],"description":"Whether the copy in the source vault was removed"},"reason":{"type":"string","description":"Why a secret is blocked, e.g. limit_reached or egress_header_conflict"}}}}}},"MoveVaultSecrets":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"from":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string","minLength":1,"maxLength":128},"description":"The vaults to move out of (vlt_…)"},"replace":{"description":"Clashing names to overwrite in this vault with the named source's secret","maxItems":200,"type":"array","items":{"type":"object","properties":{"from":{"type":"string","minLength":1,"maxLength":128},"name":{"type":"string","minLength":1,"maxLength":256}},"required":["from","name"]}},"dry_run":{"type":"boolean"}},"required":["from"]},"CreateVault":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"display_name":{"type":"string","minLength":1,"maxLength":128}},"required":["display_name"]},"CreateVaultSecret":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"display_name":{"type":"string","minLength":1,"maxLength":128},"auth":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"static_bearer"},"mcp_server_url":{"type":"string","format":"uri","description":"https, public host"},"token":{"type":"string","minLength":1}},"required":["type","mcp_server_url","token"]},{"type":"object","properties":{"type":{"type":"string","const":"mcp_oauth"},"mcp_server_url":{"type":"string","format":"uri","description":"https, public host"},"access_token":{"type":"string","minLength":1},"scope":{"type":"string"},"expires_at":{"type":"string"},"refresh":{"type":"object","properties":{"token_endpoint":{"type":"string","format":"uri"},"client_id":{"type":"string","minLength":1},"client_secret":{"type":"string"},"refresh_token":{"type":"string","minLength":1},"token_endpoint_auth":{"default":"none","type":"string","enum":["none","client_secret_basic","client_secret_post"]}},"required":["token_endpoint","client_id","refresh_token"]}},"required":["type","mcp_server_url","access_token"]},{"type":"object","properties":{"type":{"type":"string","const":"environment_variable"},"secret_name":{"type":"string","minLength":1,"maxLength":128,"description":"A valid environment variable name"},"value":{"type":"string","minLength":1},"allowed_hosts":{"default":[],"maxItems":64,"type":"array","items":{"type":"string","minLength":1}},"injection_location":{"default":{"header":true,"body":false},"type":"object","properties":{"header":{"type":"boolean"},"body":{"type":"boolean"},"header_name":{"type":"string"},"value_template":{"type":"string","minLength":1,"maxLength":256}}}},"required":["type","secret_name","value"]}]}},"required":["display_name","auth"]},"UpdateVaultSecret":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"display_name":{"type":"string","minLength":1,"maxLength":128},"value":{"type":"string","minLength":1},"token":{"type":"string","minLength":1},"allowed_hosts":{"maxItems":64,"type":"array","items":{"type":"string","minLength":1}},"injection_location":{"type":"object","properties":{"header":{"type":"boolean"},"body":{"type":"boolean"},"header_name":{"type":"string"},"value_template":{"type":"string","minLength":1,"maxLength":256}}}}},"SessionHandoff":{"type":"object","description":"`resolved_mode` is how the move was actually made: `native_fork` when source and target share a harness and the pod's own state could be forked, else `summary` — a written handover the target reads as history, never as instructions. `target_session` is null until the move completes.","required":["id","status","resolved_mode","status_url","created_at","updated_at"],"properties":{"id":{"type":"string","description":"handoff_…"},"source_session":{"type":["string","null"]},"target_session":{"type":["string","null"]},"last_message_id":{"type":["string","null"]},"target_agent":{"type":["string","null"]},"status":{"type":"string","description":"Lowercased HandoffStatus: pending · checkpointing · provisioning · restoring · completed · retry_wait · failed · cancelled. Terminal: completed, failed, cancelled."},"resolved_mode":{"type":"string","enum":["native_fork","summary"]},"resolution_reason":{"type":["string","null"]},"checkpoint":{"type":["object","null"],"description":"What was carried across, without its content","properties":{"format":{"type":["string","null"]},"format_version":{"type":["string","null"]},"sha256":{"type":["string","null"]},"size_bytes":{"type":["integer","null"]}}},"summary":{"type":["object","null"],"description":"What was carried across, without its content","properties":{"format":{"type":["string","null"]},"format_version":{"type":["string","null"]},"sha256":{"type":["string","null"]},"size_bytes":{"type":["integer","null"]}}},"error":{"type":["object","null"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"retryable":{"type":"boolean"}}},"status_url":{"type":"string","description":"GET it to poll the move"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"}}},"RequestSessionHandoff":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"target_agent":{"type":"string","minLength":1,"maxLength":256},"last_message_id":{"type":"string","minLength":1,"maxLength":256}},"required":["target_agent"],"additionalProperties":false},"TaskFile":{"type":"object","required":["path","size_bytes","sha256","updated_at","updated_by_session"],"properties":{"path":{"type":"string"},"size_bytes":{"type":"integer"},"sha256":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"updated_by_session":{"type":["string","null"],"description":"The session that last wrote it; null when a person or developer did"}}},"TaskFileVersion":{"type":"object","required":["id","sha256","size_bytes","session","conflict","created_at"],"properties":{"id":{"type":"string"},"sha256":{"type":"string"},"size_bytes":{"type":"integer"},"session":{"type":["string","null"]},"conflict":{"type":"boolean","description":"The writer had not seen what was current when it wrote"},"created_at":{"type":"string","format":"date-time"}}},"TaskSummary":{"type":"object","description":"A task is a root session and every session descended from it: helpers the agent created and branches it was handed off to. A session with no parent is a task of one.","required":["id","title","attention","status_line","open_request_count","session_count","sessions","agent_id","agent_type","llm","archived","last_activity_at","created_at"],"properties":{"id":{"type":"string","description":"sess_… — the root session's id"},"title":{"type":["string","null"]},"attention":{"type":"string","enum":["needs_you","working","done","idle"],"description":"What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new."},"status_line":{"type":["string","null"],"description":"One line, at most 140 characters, on where it stands: the oldest question waiting on the caller, else the start of the latest thing an agent said. Null when no agent has said anything."},"open_request_count":{"type":"integer","description":"Open requests addressed to the caller"},"session_count":{"type":"integer","description":"The root session plus its helper and handoff sessions"},"sessions":{"type":"array","description":"Every session in the task, root first, each with its own share of the state: its own open requests, its own run and its own latest result, measured against the task's seen mark.","items":{"type":"object","required":["id","role","attention","status_line"],"properties":{"id":{"type":"string","description":"sess_…"},"role":{"type":"string","enum":["primary","helper","handoff"]},"attention":{"type":"string","enum":["needs_you","working","done","idle"],"description":"What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new."},"status_line":{"type":["string","null"],"description":"One line, at most 140 characters, on where it stands: the oldest question waiting on the caller, else the start of the latest thing an agent said. Null when no agent has said anything."}}}},"agent_id":{"type":["string","null"],"description":"The root session's agent (agent_…)"},"agent_type":{"type":"string"},"llm":{"type":"string"},"archived":{"type":"boolean"},"last_activity_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"Task":{"type":"object","required":["id","title","attention","status_line","open_request_count","session_count","sessions","agent_id","agent_type","llm","archived","last_activity_at","created_at","consumed_cost","sessions","requests","completion_answer"],"properties":{"id":{"type":"string","description":"sess_… — the root session's id"},"title":{"type":["string","null"]},"attention":{"type":"string","enum":["needs_you","working","done","idle"],"description":"What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new."},"status_line":{"type":["string","null"],"description":"One line, at most 140 characters, on where it stands: the oldest question waiting on the caller, else the start of the latest thing an agent said. Null when no agent has said anything."},"open_request_count":{"type":"integer","description":"Open requests addressed to the caller"},"session_count":{"type":"integer","description":"The root session plus its helper and handoff sessions"},"sessions":{"type":"array","description":"The root first, then the others in the order they joined","items":{"type":"object","required":["id","role","attention","status_line","title","status","agent_id","agent_type","llm","consumed_cost","created_at"],"properties":{"id":{"type":"string","description":"sess_…"},"role":{"type":"string","enum":["primary","helper","handoff"]},"attention":{"type":"string","enum":["needs_you","working","done","idle"],"description":"What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new."},"status_line":{"type":["string","null"],"description":"One line, at most 140 characters, on where it stands: the oldest question waiting on the caller, else the start of the latest thing an agent said. Null when no agent has said anything."},"title":{"type":["string","null"]},"status":{"type":"string","enum":["provisioning","idle","running","terminated"]},"agent_id":{"type":["string","null"]},"agent_type":{"type":"string"},"llm":{"type":"string"},"consumed_cost":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Integer US cents, as a string"},"currency":{"type":"string","enum":["USD"]}}},"model_paid_by":{"type":"object","description":"Who pays for the model in this session: the wallet, or the caller's own account at a vendor. Runtime is charged to the wallet either way. Present where external accounts are turned on.","required":["source"],"properties":{"source":{"type":"string","enum":["wallet","account"]},"vendor":{"type":"string"},"name":{"type":"string"}}},"created_at":{"type":"string","format":"date-time"}}}},"agent_id":{"type":["string","null"],"description":"The root session's agent (agent_…)"},"agent_type":{"type":"string"},"llm":{"type":"string"},"archived":{"type":"boolean"},"last_activity_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"consumed_cost":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Integer US cents, as a string"},"currency":{"type":"string","enum":["USD"]}},"description":"Billed cost summed over every session in the task, a paid agent's flat fee included"},"completion_answer":{"type":["object","null"],"description":"What the caller said about whether this task did the job; null until they answer. Other people's answers are not shown.","required":["did_the_job","answered_at"],"properties":{"did_the_job":{"type":"boolean"},"answered_at":{"type":"string","format":"date-time"}}},"payer":{"type":"object","description":"Who pays for it, decided once when it was created and never changed. Present only when a payer was recorded, which happens in a team workspace where workspace wallets are on; absent means its owner's own balance pays.","required":["type"],"properties":{"type":{"type":"string","enum":["workspace","personal"],"description":"`workspace`: the team workspace's own wallet. `personal`: the balance of the person who started it."},"workspace":{"type":"object","description":"The paying workspace; only with type workspace","properties":{"slug":{"type":"string"},"name":{"type":"string"}}}}},"agent_fees":{"type":"array","description":"The flat fees of paid agents in this task. Present only when the task has one.","items":{"type":"object","required":["session_id","handle","fee","status","dispute_until","dispute"],"properties":{"session_id":{"type":"string"},"handle":{"type":"string"},"fee":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}}},"status":{"type":"string","enum":["awaiting_confirmation","declined","held","captured","disputed","released","refunded"],"description":"`held`: set aside from the caller's credit when the task started. `captured`: taken, on the task's first result. `released`: given back because the task was archived or deleted without a result. `disputed`, `refunded`: see the dispute route."},"dispute_until":{"type":["string","null"],"format":"date-time","description":"Until when the caller may say the task was not completed; null unless the fee is captured and undisputed"},"dispute":{"type":["object","null"],"description":"What the caller said and how it was ruled; null when the fee was never disputed.","required":["reason","disputed_at","ruling","ruled_at"],"properties":{"reason":{"type":"string"},"disputed_at":{"type":"string","format":"date-time"},"ruling":{"type":["string","null"],"enum":["refunded","upheld",null],"description":"Null while a reviewer has not decided. `upheld`: the charge stands and `status` is `captured` again."},"ruled_at":{"type":["string","null"],"format":"date-time"}}}}}},"requests":{"type":"array","description":"Open requests addressed to the caller, oldest first. Answer one by sending its reply to `session_id` as a message, exactly as a question is answered in that session.","items":{"type":"object","required":["id","session_id","message_id","kind","subject","question","options","allow_free_text","required_user_id","due_at","created_at"],"properties":{"id":{"type":"string","description":"The request id the agent or the platform assigned"},"session_id":{"type":"string","description":"The session that is waiting (sess_…)"},"message_id":{"type":"string"},"kind":{"type":"string","enum":["question","approval","connect_app","connect_account","spend"],"description":"`question`: an agent asked. `approval`: a tool needs the caller's go-ahead before it runs (options `allow`, `deny`), or a workspace rule asks for it before the task itself starts (options `confirm`, `decline`; nothing has run, and declining archives the task). `connect_app`: the agent needs an app that is not connected; it resolves by itself when the caller connects the app, or by answering `skip`. `connect_account`: the task cannot run without the caller's own account at a vendor, or that account has no usage left; what the caller sent is kept and nothing has run. It resolves by itself when the account is connected (`POST /external_accounts`), or by answering `use_wallet` (offered only when the account is exhausted or expired and the task can run on a platform model) or `wait`. `spend`: an agent whose maker asks a flat fee is about to be used for the first time at that price, either as this task's own agent (nothing has run, and nothing runs until it is answered) or as a helper an agent in the task wants to hire. Answer `confirm` or `decline`; a confirmation is remembered for that agent at that price."},"subject":{"type":["string","null"],"description":"For `connect_app`, the app's slug; for `connect_account`, the vendor; for `spend`, the agent's handle"},"question":{"type":"string"},"options":{"type":"array","items":{"type":"object","required":["id","label"],"properties":{"id":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"}}}},"allow_free_text":{"type":"boolean"},"required_user_id":{"type":["string","null"],"description":"Set when only one person may answer"},"due_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}}}}},"PushSubscription":{"type":"object","description":"One browser the caller asked to be notified in. Its keys are never returned.","required":["id","kind","endpoint","created_at","last_seen_at"],"properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["web"]},"endpoint":{"type":"string","description":"The push service's address for that browser."},"created_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time","description":"When that browser last subscribed."}}},"NotificationPreferences":{"type":"object","description":"The caller's own choices. They follow the person across workspaces.","required":["email","push"],"properties":{"push":{"type":"object","required":["needs_you","done"],"description":"Which kinds reach the browsers the caller subscribed (`/push-subscriptions`). Both on unless turned off; without a subscribed browser nothing is pushed.","properties":{"needs_you":{"type":"boolean","description":"Notify my browsers when one of my tasks starts waiting on me."},"done":{"type":"boolean","description":"Notify my browsers when one of my tasks produces a result while I am away."}}},"email":{"type":"object","required":["needs_you","done"],"properties":{"needs_you":{"type":"boolean","description":"Email me when one of my tasks starts waiting on me and I have not looked at it. On unless turned off."},"done":{"type":"boolean","description":"Email me when one of my tasks produces a result while I am away. Off unless turned on."}}}}},"ConnectorApp":{"type":"object","description":"An app a person can connect so their agents can use it.","required":["slug","name","description"],"properties":{"slug":{"type":"string","description":"The app's id, used wherever an app is named."},"name":{"type":"string"},"description":{"type":"string"}}},"ConnectorConnection":{"type":"object","description":"One account the caller connected. A person can connect several accounts of the same app.","required":["id","app","app_name","label","created_at"],"properties":{"id":{"type":"string"},"app":{"type":"string","description":"The app's slug."},"app_name":{"type":"string"},"label":{"type":"string","description":"The account's name at the app, usually an email address."},"created_at":{"type":"string","format":"date-time"}}},"OauthClient":{"type":"object","description":"An app registered to sign people in with their account.","required":["id","name","redirect_uris","scopes","review_status","test_users","created_at","updated_at"],"properties":{"id":{"type":"string","description":"The client id the app presents when it sends a person to sign in."},"name":{"type":"string","minLength":1,"maxLength":80,"description":"Shown to people when they are asked to allow the app."},"redirect_uris":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"string"},"description":"Where the app may send people back after they decide. Matched exactly: no wildcards, no fragments. Must be https; `http://localhost` and `http://127.0.0.1` are accepted while the app is not reviewed."},"scopes":{"type":"array","minItems":1,"items":{"type":"string","enum":["read","write"]},"description":"What the app may ask a person for. `read` sees their tasks, agents and sessions; `write` also starts and changes them."},"test_users":{"type":"array","maxItems":10,"items":{"type":"string","format":"email"},"description":"People besides you who may use the app before it is reviewed, by the email address of their account."},"review_status":{"type":"string","enum":["unreviewed","approved"],"description":"An unreviewed app works only for its owner and its test users, and people are told it has not been reviewed."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"CatalogAgent":{"type":"object","required":["handle","kind","engine_type","agent_id","visibility","seller","name","tagline","description","does","does_not","categories","examples","requirements","pricing","stats","conformance","created_at"],"properties":{"handle":{"type":"string","description":"Globally unique and stable: lower-case letters, digits and underscores. What a person types after \"/\"."},"kind":{"type":"string","enum":["engine","agent"],"description":"A platform engine, or an agent a person listed"},"engine_type":{"type":["string","null"],"description":"The agent type to create an agent with, for an engine listing"},"agent_id":{"type":["string","null"],"description":"The agent one of the caller's own workspace listings stands for; null for an engine and for another person's agent"},"visibility":{"type":"string","enum":["public","workspace"],"description":"public for everyone: an engine, or another person's agent that was reviewed and approved. workspace for the caller's own listing, whether or not it is also public."},"seller":{"type":["object","null"],"description":"Who made a public agent that is not a platform engine, by the name they chose. Null for an engine and for the caller's own listing.","required":["name"],"properties":{"name":{"type":"string"}}},"name":{"type":"string"},"tagline":{"type":"string","description":"One line, at most 140 characters"},"description":{"type":"string"},"does":{"type":"array","items":{"type":"string"},"description":"What it does. Empty when not yet written; never guessed."},"does_not":{"type":"array","items":{"type":"string"},"description":"What it does not do. Empty when not yet written."},"categories":{"type":"array","items":{"type":"string","enum":["websites","content","video","code","research","general"]}},"examples":{"type":"array","items":{"type":"string"},"description":"Example tasks"},"requirements":{"type":"object","description":"What the agent needs, stated rather than hidden. `mcp_servers` says whether it can use MCP servers; `website` is the engine's own site. `hosted_by_seller: { host }` is present when the agent runs on its maker's own server instead of a sandbox: what a person sends it, and the files of the task, go to that host, and a person's first task with it waits for them to agree (a task request).","additionalProperties":true},"pricing":{"type":"object","description":"`{ mode: \"usage\" }`: the model and tool usage the task incurs, with no agent fee. `{ mode: \"per_task\", fee: { amount, currency } }`: usage, plus a flat fee the agent's maker asks for each task; `amount` is whole US cents as a string. Starting such an agent asks the person to confirm the price the first time (a task request of kind `spend`), holds the fee on their credit when the task starts and takes it when the task gives its first result.","additionalProperties":true},"stats":{"type":"object","description":"Counts from real use, recounted hourly; never estimated. `uses`: sessions started on the agent. `comparisons` and `wins`: decided side-by-side comparisons the agent took part in, and the ones a person picked it in. `completed_yes` and `completed_no`: people who said a task on this agent did the job, and people who said it did not (`PUT /tasks/{id}/completion_answer`).","required":["uses","comparisons","wins","completed_yes","completed_no"],"properties":{"uses":{"type":"integer"},"comparisons":{"type":"integer"},"wins":{"type":"integer"},"completed_yes":{"type":"integer"},"completed_no":{"type":"integer"},"usage":{"type":["object","null"],"description":"What one task typically consumes: medians over the agent's sessions of the last 30 days that metered model usage. Null until at least 10 such sessions exist.","required":["tasks","tokens","tool_calls","cost_usd"],"properties":{"tasks":{"type":"integer","description":"Sessions the medians are taken over"},"tokens":{"type":"integer","description":"Median input plus output tokens"},"tool_calls":{"type":"integer","description":"Median tool calls"},"cost_usd":{"type":"number","description":"Median billed cost in USD"}}}}},"conformance":{"type":["object","null"],"description":"The verdicts of the listing's latest finished conformance run; for another person's agent, of the run it was submitted with. Null when it has never finished one.","required":["required_passed","all_passed","checked_at"],"properties":{"required_passed":{"type":"boolean","description":"No required check failed and at least one ran"},"all_passed":{"type":"boolean","description":"Every check ran and passed"},"checked_at":{"type":"string","format":"date-time"}}},"created_at":{"type":"string","format":"date-time"}}},"ListingSubmissionState":{"type":"object","required":["open","missing","submission","published","taken_down"],"properties":{"open":{"type":"boolean","description":"Whether this workspace may submit listings to the public Market"},"missing":{"type":"array","items":{"type":"string"},"description":"What still has to be true before the listing can be submitted, in words. Empty when it can be."},"pricing":{"type":"object","description":"Present only where this workspace may set a flat fee on its public listings.","required":["seller_share_percent","fee_cents_min","fee_cents_max"],"properties":{"seller_share_percent":{"type":"number","description":"The part of each fee the seller keeps"},"fee_cents_min":{"type":"integer"},"fee_cents_max":{"type":"integer"}}},"submission":{"type":["object","null"],"description":"The latest submission; null when the listing has never been submitted.","required":["status","seller_name","submitted_at","decided_at","reason"],"properties":{"status":{"type":"string","enum":["in_review","approved","sent_back","withdrawn"]},"seller_name":{"type":"string"},"submitted_at":{"type":"string","format":"date-time"},"decided_at":{"type":["string","null"],"format":"date-time"},"reason":{"type":["string","null"],"description":"What the reviewer wrote when sending it back"},"fee":{"type":"object","additionalProperties":false,"required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^[1-9][0-9]*$","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}},"description":"The flat fee per task it was submitted with; absent when it has none"}}},"published":{"type":["object","null"],"description":"The approved version being served to everyone; null when the listing is not public.","required":["seller_name","approved_at"],"properties":{"seller_name":{"type":"string"},"approved_at":{"type":"string","format":"date-time"},"fee":{"type":"object","additionalProperties":false,"required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^[1-9][0-9]*$","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}},"description":"The flat fee per task of the approved version; absent when it has none"}}},"taken_down":{"type":["object","null"],"description":"Set when a reviewer took the public listing down and it has not been submitted again.","required":["at","reason"],"properties":{"at":{"type":"string","format":"date-time"},"reason":{"type":["string","null"]}}},"scheduled_check":{"type":"object","description":"What the scheduled checks of the approved version found. A public listing's approved version is checked when it is approved and then by the weekly conformance sweep, as its seller and on the seller's credit for usage, under a spend cap. Absent when the listing is not public.","required":["passing","reason","running","checked_at","next_at"],"properties":{"passing":{"type":["boolean","null"],"description":"Whether the required checks passed at the last scheduled run that finished; null before the first. False takes the listing's `conformance.required_passed` away for everyone; the listing stays public."},"reason":{"type":["string","null"],"description":"The required checks that failed, or why the latest run was skipped or could not finish"},"checked_at":{"type":["string","null"],"format":"date-time"},"running":{"type":"boolean","description":"Whether a scheduled run of this version is going now"},"next_at":{"type":"string","format":"date-time"}}}}},"ConformanceRun":{"type":"object","required":["id","handle","status","started_at","finished_at","reason","required_passed","all_passed","report"],"properties":{"id":{"type":"string"},"handle":{"type":"string"},"status":{"type":"string","enum":["running","finished","failed"],"description":"A run still going after 30 minutes is reported as failed."},"started_at":{"type":"string","format":"date-time"},"finished_at":{"type":["string","null"],"format":"date-time"},"reason":{"type":["string","null"],"description":"Why the run could not finish; null unless it failed"},"required_passed":{"type":"boolean","description":"No required check failed and at least one ran. False until the run finished."},"all_passed":{"type":"boolean","description":"Every check ran and passed. False until the run finished."},"report":{"type":["object","null"],"description":"Every check with its outcome; null until the run finished.","required":["handle","required_passed","all_passed","checks"],"properties":{"handle":{"type":"string"},"required_passed":{"type":"boolean"},"all_passed":{"type":"boolean"},"checks":{"type":"array","items":{"type":"object","required":["id","required","status","reason","seconds"],"properties":{"id":{"type":"string"},"required":{"type":"boolean"},"status":{"type":"string","enum":["pass","fail","skipped"],"description":"skipped means the suite could not run the check; it is not a pass"},"reason":{"type":["string","null"],"description":"Why it failed or was skipped; null when it passed"},"seconds":{"type":"integer"}}}}}}}},"EnvironmentListing":{"type":"object","required":["id","handle","name","tagline","description","categories","packages","tools","networking","installs","seller","visibility","conformance","created_at"],"properties":{"id":{"type":"string","description":"The listing id (lst_…)"},"handle":{"type":"string","description":"Globally unique within environment listings; lower-case letters, digits and underscores"},"name":{"type":"string"},"tagline":{"type":"string","description":"One line, at most 140 characters"},"description":{"type":"string"},"categories":{"type":"array","items":{"type":"string","enum":["development","data","ml","security","web","general"]}},"packages":{"type":["object","null"],"description":"The listed environment's package configuration, or null when it has none","additionalProperties":true},"tools":{"type":["object","null"],"description":"The listed environment's tool policy, or null when it has none","additionalProperties":true},"networking":{"type":["object","null"],"description":"The listed environment's networking configuration, or null when it has none","additionalProperties":true},"installs":{"type":"integer","description":"How many workspaces have installed this listing"},"seller":{"type":"object","description":"The workspace that published the listing","required":["name"],"properties":{"name":{"type":"string"}}},"visibility":{"type":"string","enum":["workspace","public"],"description":"workspace = visible only to the owning workspace; public = visible to all"},"conformance":{"type":"null","description":"Reserved; always null in this release"},"created_at":{"type":"string","format":"date-time"}}},"ListingHosting":{"type":"object","description":"Where a listing's agent runs.","required":["hosting"],"properties":{"hosting":{"type":"string","enum":["platform","seller"],"description":"`platform`: in a sandbox. `seller`: on the maker's own server."},"endpoint_url":{"type":"string","description":"The address tasks are sent to. Present when `hosting` is `seller`."},"secret":{"type":"string","description":"The secret requests are signed with. Present only in the response that made or replaced it."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"Artifact":{"type":"object","required":["id","task_id","name","version","entry","files","share_url","created_at","updated_at"],"properties":{"id":{"type":"string"},"task_id":{"type":"string","description":"The task it belongs to (sess_…)"},"name":{"type":"string","description":"Unique within the task; publishing under the same name adds a version"},"version":{"type":"integer","description":"The current revision"},"entry":{"type":"string","description":"The file opened first"},"files":{"type":"array","items":{"type":"object","required":["path","sha256","size_bytes"],"properties":{"path":{"type":"string"},"sha256":{"type":"string"},"size_bytes":{"type":"integer"}}}},"share_url":{"type":["string","null"],"description":"The public link, or null while not shared"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ArtifactRevision":{"type":"object","required":["version","entry","files","published_by_session","created_at"],"properties":{"version":{"type":"integer"},"entry":{"type":"string"},"files":{"type":"array","items":{"type":"object","required":["path","sha256","size_bytes"],"properties":{"path":{"type":"string"},"sha256":{"type":"string"},"size_bytes":{"type":"integer"}}}},"published_by_session":{"type":["string","null"],"description":"The session that published it; null when a person or developer did"},"created_at":{"type":"string","format":"date-time"}}},"HarnessProfile":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9_-]{1,39}$"},"name":{"type":"string","minLength":1,"maxLength":200},"version":{"type":"string","minLength":1,"maxLength":128},"distribution":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"object","properties":{"oci":{"type":"object","properties":{"image":{"type":"string","pattern":"^[^@]+@sha256:[0-9a-f]{64}$"}},"required":["image"]}},"required":["oci"]}]},"auth_command":{"type":"array","items":{"type":"string"}},"bundled_mcp_servers":{"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"configuration_files":{"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"credential_args":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"graceful_exit_timeout_seconds":{"type":"number"},"home_directories":{"type":"array","items":{"type":"string"}},"managed_model_id_template":{"type":"string"},"native_provider_setup":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"pipeline":{"type":"string"},"prerequisites":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"request_timeout_seconds":{"type":"number"},"requirements":{"type":"array","items":{"type":"string"}},"session_close_before_exit":{"type":"boolean"},"session_config_options":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"session_load_supported":{"type":"boolean"},"session_parameters":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"subscription_files":{"type":"boolean"},"docker_target":{"type":"string"},"tools":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"title":{"type":"string"},"requires":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["id","kind"]}},"features":{"type":"array","items":{"type":"string"}}},"required":["id","name","version"],"description":"The runtime description of a workspace harness: the distribution spec (npx, uvx or binary), optional auth command, bundled MCP servers, tools, features and other catalog fields the installer reads when it builds the template image."},"Harness":{"type":"object","required":["id","handle","name","profile","model_billing","created_at","updated_at"],"properties":{"id":{"type":"string","description":"hrn_… — the public id"},"handle":{"type":"string","description":"Short slug within the workspace (e.g. my-harness)"},"name":{"type":"string"},"profile":{"$ref":"#/components/schemas/HarnessProfile"},"model_billing":{"type":"string","enum":["gateway","external"],"description":"gateway: model calls are billed through the platform wallet. external: the harness manages billing itself."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"HarnessList":{"type":"object","required":["harnesses"],"properties":{"harnesses":{"type":"array","items":{"$ref":"#/components/schemas/Harness"}}}},"HarnessVersion":{"type":"object","required":["id","harness_id","version","status","profile","created_at","updated_at"],"properties":{"id":{"type":"string","description":"hrnv_… — internal version row id"},"harness_id":{"type":"string","description":"hrn_… — the parent harness"},"version":{"type":"string","description":"Version string, e.g. v1-4096m"},"status":{"type":"string","enum":["pending","building","ready","current","revoked"],"description":"pending: registered, build not started. building: E2B template build in progress. ready: build succeeded; can be promoted. current: the version agents are created against; at most one per harness. revoked: explicitly withdrawn; cannot be promoted or used for new sessions."},"profile":{"$ref":"#/components/schemas/HarnessProfile"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"HarnessVersionList":{"type":"object","required":["versions"],"properties":{"versions":{"type":"array","items":{"$ref":"#/components/schemas/HarnessVersion"}}}},"CreateHarness":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"handle":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]{1,38}[a-z0-9]$"},"name":{"type":"string","minLength":1,"maxLength":200},"profile":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9_-]{1,39}$"},"name":{"type":"string","minLength":1,"maxLength":200},"version":{"type":"string","minLength":1,"maxLength":128},"distribution":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"object","properties":{"oci":{"type":"object","properties":{"image":{"type":"string","pattern":"^[^@]+@sha256:[0-9a-f]{64}$"}},"required":["image"]}},"required":["oci"]}]},"auth_command":{"type":"array","items":{"type":"string"}},"bundled_mcp_servers":{"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"configuration_files":{"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"credential_args":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"graceful_exit_timeout_seconds":{"type":"number"},"home_directories":{"type":"array","items":{"type":"string"}},"managed_model_id_template":{"type":"string"},"native_provider_setup":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"pipeline":{"type":"string"},"prerequisites":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"request_timeout_seconds":{"type":"number"},"requirements":{"type":"array","items":{"type":"string"}},"session_close_before_exit":{"type":"boolean"},"session_config_options":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"session_load_supported":{"type":"boolean"},"session_parameters":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"subscription_files":{"type":"boolean"},"docker_target":{"type":"string"},"tools":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"title":{"type":"string"},"requires":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["id","kind"]}},"features":{"type":"array","items":{"type":"string"}}},"required":["id","name","version"]},"model_billing":{"default":"external","type":"string","enum":["gateway","external"]}},"required":["handle","name","profile"]},"PatchHarness":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"model_billing":{"type":"string","enum":["gateway","external"]}}},"CreateHarnessVersion":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"version":{"type":"string","minLength":1,"maxLength":128},"profile":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9_-]{1,39}$"},"name":{"type":"string","minLength":1,"maxLength":200},"version":{"type":"string","minLength":1,"maxLength":128},"distribution":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"object","properties":{"oci":{"type":"object","properties":{"image":{"type":"string","pattern":"^[^@]+@sha256:[0-9a-f]{64}$"}},"required":["image"]}},"required":["oci"]}]},"auth_command":{"type":"array","items":{"type":"string"}},"bundled_mcp_servers":{"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"configuration_files":{"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"credential_args":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"graceful_exit_timeout_seconds":{"type":"number"},"home_directories":{"type":"array","items":{"type":"string"}},"managed_model_id_template":{"type":"string"},"native_provider_setup":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"pipeline":{"type":"string"},"prerequisites":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"request_timeout_seconds":{"type":"number"},"requirements":{"type":"array","items":{"type":"string"}},"session_close_before_exit":{"type":"boolean"},"session_config_options":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"session_load_supported":{"type":"boolean"},"session_parameters":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"subscription_files":{"type":"boolean"},"docker_target":{"type":"string"},"tools":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"title":{"type":"string"},"requires":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["id","kind"]}},"features":{"type":"array","items":{"type":"string"}}},"required":["id","name","version"]}},"required":["version"]},"VerifyHarnessVersion":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"listing":{"type":"string","minLength":1}},"required":["listing"]},"WorkerPool":{"type":"object","required":["id","name","created_at","updated_at"],"properties":{"id":{"type":"string","description":"wpool_…"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"WorkerPoolList":{"type":"object","required":["worker_pools"],"properties":{"worker_pools":{"type":"array","items":{"$ref":"#/components/schemas/WorkerPool"}}}},"WorkerPoolCreated":{"type":"object","required":["worker_pool","token"],"properties":{"worker_pool":{"$ref":"#/components/schemas/WorkerPool"},"token":{"type":"string","description":"A wpt_… bearer token the worker machine passes to the connect endpoint. Shown only once — rotate it from /worker-pools/{id}/tokens if lost."}}},"WorkerPoolTokenRotated":{"type":"object","required":["token"],"properties":{"token":{"type":"string","description":"The new wpt_… token. The previous token is immediately invalidated."}}},"Worker":{"type":"object","required":["id","pool_id","label","status","created_at"],"properties":{"id":{"type":"string","description":"wrk_…"},"pool_id":{"type":"string","description":"wpool_…"},"label":{"type":"string","description":"Human-readable label the worker sent at connect time."},"image_digest":{"type":"string"},"status":{"type":"string","enum":["connected","busy","offline"],"description":"`connected` — idle and ready; `busy` — running a session; `offline` — disconnected."},"last_seen_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"WorkerList":{"type":"object","required":["workers"],"properties":{"workers":{"type":"array","items":{"$ref":"#/components/schemas/Worker"}}}},"CreateWorkerPool":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128}},"required":["name"]}}},"paths":{"/billing":{"get":{"summary":"Read credit balance and card availability [read]","description":"Returns the caller's credit balance and whether a card is on file. No card details are returned.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["balance_usd","card_on_file"],"properties":{"balance_usd":{"type":"number"},"card_on_file":{"type":"boolean"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/billing/card-setup":{"post":{"summary":"Start saving a payment card [write]","description":"Returns a hosted card form URL to open in a browser. Saving the card does not charge it; auto top-up can charge it when a later session starts below the configured threshold. No request body is required.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/products":{"get":{"summary":"Products, permitted inputs and configuration, prices and certified capabilities [read]","security":[{"bearerAuth":[]}],"description":"Every agent in the catalog (GET /catalog/agents) is also listed, as `@handle`; it is available when its latest check run passed the required checks.","responses":{"200":{"description":"Executable product catalog"}}}},"/runs":{"post":{"summary":"Run a product [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Scoped to the authenticated person, universe, operation, and target. Changed input returns 409; token renewal preserves identity."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"product":{"type":"string","minLength":1,"maxLength":240},"input":{},"addons":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"session_id":{"type":"string","minLength":1},"stream":{"type":"boolean"},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["product","input"],"additionalProperties":false}}}},"description":"String input is a shortcut. Agent objects preserve one user message and optional system message. Direct Agent Runs prepare a Session with platform billing; an existing Session retains its payer and billing settings. Non-streaming waits up to ten seconds. SSE begins with the durable Run identity. Disconnect never cancels execution. A catalog handle (`@handle`) runs that agent as one turn of a new session of it, charged as that session is: `addons` may set `model`, within the agent's engine, and `instructions`, files added after the agent's own, and nothing else; a `user.message` sent to the Run (POST /runs/{id}/events) is the next turn of that session and a Run of its own. When a Run of a handle ends, each webhook endpoint of the workspace subscribed to `run.completed`, `run.interrupted`, `run.failed` or `run.blocked` receives that event once, signed like every other webhook. A handle whose agent has not passed its checks is refused with `listing_not_checked` or `listing_checks_failed`.","responses":{"200":{"description":"Durable Run identity, status, output and references to authoritative billing.","content":{"application/json":{"schema":{"type":"object","properties":{"run":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"id":{"type":"string"},"product":{"type":["string","null"]},"session_id":{"type":["string","null"]},"status":{"type":"string","enum":["queued","running","waiting_input","stopping","completed","interrupted","failed","blocked","reconciling"]},"output":{},"output_available":{"type":"boolean"},"usage":{},"billing":{},"error":{},"artifact":{"type":"object","properties":{"id":{"type":"string"},"mediaType":{"type":"string"},"url":{"type":"string","format":"uri"}},"required":["id","mediaType","url"]},"source":{"type":"object","properties":{"goal_id":{"type":"string"},"iteration":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"routine_run_id":{"type":"string"},"routine_id":{"type":"string"}}},"created_at":{"type":"string"},"completed_at":{"type":["string","null"]}},"required":["id","product","session_id","status","output","usage","billing","error","created_at","completed_at"]}}}}}},"202":{"description":"Durable Run identity, status, output and references to authoritative billing.","content":{"application/json":{"schema":{"type":"object","properties":{"run":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"id":{"type":"string"},"product":{"type":["string","null"]},"session_id":{"type":["string","null"]},"status":{"type":"string","enum":["queued","running","waiting_input","stopping","completed","interrupted","failed","blocked","reconciling"]},"output":{},"output_available":{"type":"boolean"},"usage":{},"billing":{},"error":{},"artifact":{"type":"object","properties":{"id":{"type":"string"},"mediaType":{"type":"string"},"url":{"type":"string","format":"uri"}},"required":["id","mediaType","url"]},"source":{"type":"object","properties":{"goal_id":{"type":"string"},"iteration":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"routine_run_id":{"type":"string"},"routine_id":{"type":"string"}}},"created_at":{"type":"string"},"completed_at":{"type":["string","null"]}},"required":["id","product","session_id","status","output","usage","billing","error","created_at","completed_at"]}}}}}},"409":{"description":"Session busy or conflicting idempotency key"},"422":{"description":"The product cannot be run: a listed agent that has not passed its checks, or an override that is not allowed"}}}},"/runs/{id}":{"get":{"summary":"Read a Run [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Durable Run identity, status, output and references to authoritative billing.","content":{"application/json":{"schema":{"type":"object","properties":{"run":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"id":{"type":"string"},"product":{"type":["string","null"]},"session_id":{"type":["string","null"]},"status":{"type":"string","enum":["queued","running","waiting_input","stopping","completed","interrupted","failed","blocked","reconciling"]},"output":{},"output_available":{"type":"boolean"},"usage":{},"billing":{},"error":{},"artifact":{"type":"object","properties":{"id":{"type":"string"},"mediaType":{"type":"string"},"url":{"type":"string","format":"uri"}},"required":["id","mediaType","url"]},"source":{"type":"object","properties":{"goal_id":{"type":"string"},"iteration":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"routine_run_id":{"type":"string"},"routine_id":{"type":"string"}}},"created_at":{"type":"string"},"completed_at":{"type":["string","null"]}},"required":["id","product","session_id","status","output","usage","billing","error","created_at","completed_at"]}}}}}}}}},"/runs/{id}/events":{"get":{"summary":"Read durable Run events, or observe with Accept: text/event-stream [read]","security":[{"bearerAuth":[]}],"description":"A Run of a catalog handle reports `run.running`, each `agent.message` with its text, and how it ended.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"Last-Event-ID","in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Opaque Run cursor, separate from the Session transcript cursor"}}},"post":{"summary":"Target steering or an interrupt to this Run [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Scoped to the authenticated person, universe, operation, and target. Changed input returns 409; token renewal preserves identity."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"events":{"minItems":1,"maxItems":2,"type":"array","items":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"user.message"},"content":{"minItems":1,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"text":{"type":"string","minLength":1}},"required":["type","text"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"image"},"source":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"base64"},"media_type":{"type":"string","minLength":1},"data":{"type":"string","minLength":1}},"required":["type","media_type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"url"},"url":{"type":"string","minLength":1}},"required":["type","url"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"file"},"file_id":{"type":"string","minLength":1}},"required":["type","file_id"],"additionalProperties":false}]}},"required":["type","source"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"document"},"source":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"base64"},"media_type":{"type":"string","minLength":1},"data":{"type":"string","minLength":1}},"required":["type","media_type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"text"},"media_type":{"default":"text/plain","type":"string","const":"text/plain"},"data":{"type":"string","minLength":1}},"required":["type","data"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"url"},"url":{"type":"string","minLength":1}},"required":["type","url"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"file"},"file_id":{"type":"string","minLength":1}},"required":["type","file_id"],"additionalProperties":false}]},"title":{"type":["string","null"]},"context":{"type":["string","null"]}},"required":["type","source"],"additionalProperties":false}]}},"interaction_mode":{"anyOf":[{"type":"string","enum":["plan","build"]},{"type":"null"}]}},"required":["type","content"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"system.message"},"content":{"minItems":1,"maxItems":1000,"type":"array","items":{"type":"object","properties":{"type":{"type":"string","const":"text"},"text":{"type":"string","minLength":1}},"required":["type","text"],"additionalProperties":false}}},"required":["type","content"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"user.interrupt"}},"required":["type"],"additionalProperties":false}]}}},"required":["events"],"additionalProperties":false}}}},"description":"For a Run of a catalog handle, one `user.message` starts the next turn of the Run's session as a new Run and is answered with `{ run_id, status }` naming that new Run (also in `Location`); it follows the idempotency rules of starting a Run, and is refused with 409 `session_busy` while a turn of the session is still going and 409 `session_archived` once the session has ended. One `user.interrupt` stops this Run's turn and is answered with `{ run_id, status }` for this Run; a Run that has already ended is answered with the status it ended in. A system message is not accepted.","responses":{"202":{"description":"Control admitted; runtime confirmation is separate"},"409":{"description":"Run is terminal or input conflicts"}}}},"/whoami":{"get":{"summary":"Caller identity, resolved universe, effective scopes [read]","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Whoami"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes":{"get":{"summary":"List universes [read]","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["universes"],"properties":{"universes":{"type":"array","items":{"$ref":"#/components/schemas/Universe"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Create a universe [write, personal tokens only]","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUniverse"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["universe"],"properties":{"universe":{"$ref":"#/components/schemas/Universe"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}":{"get":{"summary":"Universe detail [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["universe"],"properties":{"universe":{"$ref":"#/components/schemas/Universe"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/members":{"get":{"summary":"People in the workspace and, for owners and admins, waiting invitations [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["role","members","invites"],"properties":{"role":{"type":"string","enum":["owner","admin","member"]},"members":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string"},"email":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"role":{"type":"string","enum":["owner","admin","member"]},"joined_at":{"type":"string","format":"date-time"}}}},"invites":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"role":{"type":"string","enum":["admin","member"]},"invited_by":{"type":"string"},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}}},"limit_requests":{"type":"array","description":"Members' tasks that wait for a higher monthly limit, oldest first","items":{"type":"object","properties":{"id":{"type":"string"},"session_id":{"type":"string"},"title":{"type":"string","nullable":true},"member":{"type":"object","properties":{"user_id":{"type":"string"},"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true}}},"raise_to":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}}},"held":{"type":"integer","description":"Messages the task holds and will run when the limit is raised"},"created_at":{"type":"string","format":"date-time"}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/members/{userId}":{"delete":{"summary":"Remove a non-owner from the workspace, or leave it [write]","description":"The owner removes anyone but themselves. Anyone else may name only themselves (their id, or me), which is how a person leaves; naming someone else is 403, and the owner cannot leave (400). Ends membership access, stops sharing every connection the person shared with the workspace, and closes pending and accepted invitation links. Accounts and threads remain; workspace-visible threads owned by the removed person become read-only for remaining members.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Make someone an admin or a member [write, owner]","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["role"],"properties":{"role":{"type":"string","enum":["admin","member"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/invites":{"post":{"summary":"Add people to the workspace by email [write, owner or admin]","description":"Set send_email to true to send invitation mail and include per-email delivery results. sent means provider acceptance; unavailable leaves a usable link to share. No email is sent and no delivery field is returned by default. The response carries one link token per new invitation (shown only here; links are /join/{token} on the consumer app). Each person joins through the link, or the next time they use AgentSky signed in with that verified email; an invitation lasts 30 days.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["emails"],"properties":{"emails":{"type":"array","items":{"type":"string"},"maxItems":50},"send_email":{"type":"boolean","default":false},"role":{"type":"string","enum":["admin","member"],"default":"member"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"invites":{"type":"array","items":{"type":"object"}},"links":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string"},"token":{"type":"string"}}}},"delivery":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string"},"status":{"type":"string","enum":["sent","unavailable"]}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/invites/{token}":{"get":{"summary":"What an invitation link offers the signed-in person [read]","description":"status is open (this account may join), joined, wrong_email (sent to a different address) or closed (used, withdrawn or expired).","security":[{"bearerAuth":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"},"description":"The token from the invitation link"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"workspace":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"invited_by":{"type":"string"},"role":{"type":"string","enum":["admin","member"]},"email":{"type":"string"},"status":{"type":"string","enum":["open","joined","wrong_email","closed"]}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Join the workspace through an invitation link [write]","description":"Only an account signed in with the invited, verified email may join; a credential limited to one workspace cannot.","security":[{"bearerAuth":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"workspace":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/invites/{inviteId}":{"delete":{"summary":"Withdraw an invitation that has not been taken up [write, owner or admin]","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"},{"name":"inviteId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/wallet":{"get":{"summary":"A workspace's own wallet: balance, each member's spending this month, limits, members waiting for a higher limit [read, owner or admin]","description":"404 where workspace wallets are not switched on for the workspace, 400 for a person's default workspace that has no wallet and nobody else in it, 403 for a plain member.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["wallet","month_start","members","funding","limit_requests"],"properties":{"wallet":{"type":["object","null"],"description":"Null until the workspace is given a wallet","properties":{"balance":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}}},"created_at":{"type":"string","format":"date-time"}}},"month_start":{"type":"string","format":"date-time","description":"The first instant (UTC) of the month the spending below is counted from"},"members":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string"},"email":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"role":{"type":"string","enum":["owner","admin","member"]},"spent":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}}},"monthly_limit":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}},"nullable":true}}}},"funding":{"type":"array","description":"The latest additions to the wallet, newest first","items":{"type":"object","properties":{"id":{"type":"string"},"amount":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}}},"added_by":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"}}}},"limit_requests":{"type":"array","description":"Members' tasks that wait for a higher monthly limit, oldest first","items":{"type":"object","properties":{"id":{"type":"string"},"session_id":{"type":"string"},"title":{"type":"string","nullable":true},"member":{"type":"object","properties":{"user_id":{"type":"string"},"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true}}},"raise_to":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}}},"held":{"type":"integer","description":"Messages the task holds and will run when the limit is raised"},"created_at":{"type":"string","format":"date-time"}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Give the workspace a wallet of its own [write, owner or admin]","description":"From then on a new session a member starts in the workspace is paid from this wallet unless its request names payer personal. Sessions that already exist keep the payer recorded for them. Repeating the call returns the wallet that exists.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["wallet","month_start","members","funding","limit_requests"],"properties":{"wallet":{"type":["object","null"],"description":"Null until the workspace is given a wallet","properties":{"balance":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}}},"created_at":{"type":"string","format":"date-time"}}},"month_start":{"type":"string","format":"date-time","description":"The first instant (UTC) of the month the spending below is counted from"},"members":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string"},"email":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"role":{"type":"string","enum":["owner","admin","member"]},"spent":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}}},"monthly_limit":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}},"nullable":true}}}},"funding":{"type":"array","description":"The latest additions to the wallet, newest first","items":{"type":"object","properties":{"id":{"type":"string"},"amount":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}}},"added_by":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"}}}},"limit_requests":{"type":"array","description":"Members' tasks that wait for a higher monthly limit, oldest first","items":{"type":"object","properties":{"id":{"type":"string"},"session_id":{"type":"string"},"title":{"type":"string","nullable":true},"member":{"type":"object","properties":{"user_id":{"type":"string"},"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true}}},"raise_to":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}}},"held":{"type":"integer","description":"Messages the task holds and will run when the limit is raised"},"created_at":{"type":"string","format":"date-time"}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/wallet/transfers":{"post":{"summary":"Move some of your own purchased credit into the workspace wallet [write, owner or admin]","description":"All or nothing. Only credit the caller bought moves; free credit stays. 402 insufficient_purchased_credit when the caller holds less purchased credit than the amount, 409 workspace_wallet_missing before the wallet exists. request_id makes a repeat of the same request land once (200 instead of 201); the same id with another amount is 409 idempotency_conflict.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["amount","request_id"],"properties":{"amount":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}}},"request_id":{"type":"string","minLength":8,"maxLength":100}}}}}},"responses":{"201":{"description":"Moved","content":{"application/json":{"schema":{"type":"object","properties":{"transferred":{"type":"boolean"},"balance":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/wallet/topups":{"post":{"summary":"Buy credit for the workspace wallet with your own saved card [write, owner or admin]","description":"Charges the caller's own saved card the credit plus the card processing fee and adds the credit to the workspace wallet. The caller's own balance, card and auto top-up are not changed. amount is 1000, 2000, 5000 or 10000 cents. request_id makes a repeat of the same request charge once (200 instead of 201). 409 card_required when the caller has no saved card (add one to your own account first), 402 card_declined, 409 workspace_wallet_missing before the wallet exists, 503 payments_unavailable where card payments are not set up. A workspace key or a restricted credential cannot buy credit.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["amount","request_id"],"properties":{"amount":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}}},"request_id":{"type":"string","minLength":8,"maxLength":100}}}}}},"responses":{"201":{"description":"Bought","content":{"application/json":{"schema":{"type":"object","properties":{"charged":{"type":"boolean"},"balance":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/wallet/limit-requests/{requestId}":{"post":{"summary":"Answer a member's request for a higher monthly limit [write, owner or admin]","description":"A member who reaches their monthly limit is not only refused: the task they started or wrote to waits, holding what it was given, and a request is raised (limit_requests on the wallet, and a spend request on the task). raise sets the member's limit to the amount the request offered and sends on what every waiting task of theirs was holding; decline closes this request and drops what its task held. 404 when the request is not open.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"},{"name":"requestId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["answer"],"properties":{"answer":{"type":"string","enum":["raise","decline"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"message_id":{"type":"string","nullable":true,"description":"The first message sent on to a waiting task, when one was"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/wallet/limits/{userId}":{"put":{"summary":"Set or clear a member's monthly limit on workspace wallet spending [write, owner or admin]","description":"The limit counts what the sessions that member started were charged to the workspace wallet in the calendar month (UTC), their helpers included. At the limit a message to a session the workspace pays for, a helper, a handoff and a fork are refused with 402 member_limit_reached, and a new session is created waiting; other members are not affected. monthly_limit null removes the limit. When the new limit lets the member spend again their waiting tasks continue by themselves: resumed counts the messages that were sent on.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["monthly_limit"],"properties":{"monthly_limit":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}},"nullable":true}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"resumed":{"type":"integer"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/connections":{"get":{"summary":"Connected apps people share with the workspace, and the ones it owns [read]","description":"sharing says whether members can share connected apps with this workspace; while it is on, can_connect says whether the caller may connect an app for the workspace itself, and a connection the workspace owns carries workspace_owned. A person's default workspace takes shared connections only once someone besides its owner is in it. Agents in the workspace's sessions can call through a shared connection whoever started the session; nobody but the person who shared it holds its sign-in.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceConnections"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Share one of your own connections with the workspace, or start connecting an app for it [write]","description":"With connection_id: only a connection of the caller's can be shared; answers 201 with the workspace's connections. With app, success_url and error_url (owner or admin): starts connecting an app for the workspace itself and answers 200 with the address to open in a browser; record the result with POST /universes/{slug}/connections/complete. A connection made this way belongs to the workspace, not to the person who made it, and stays when they leave. Mail and calendar apps stay personal either way (400 personal_only).","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"connection_id":{"type":"string"},"app":{"type":"string"},"success_url":{"type":"string"},"error_url":{"type":"string"}}}}}},"responses":{"200":{"description":"Started","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"}}}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceConnections"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/connections/complete":{"post":{"summary":"Record an app connected for the workspace itself [write, owner or admin]","description":"The account is checked against the workspace's own accounts at the provider; without account_id its newest one for the app is used. From then on agents in every session of the workspace can call through it. 404 when the workspace has no such account.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["app"],"properties":{"app":{"type":"string"},"account_id":{"type":"string"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceConnections"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/connections/{connectionId}":{"delete":{"summary":"Stop sharing a connection with the workspace [write, the sharer, owner or admin]","description":"Agents lose it at once. A connection the workspace owns itself is disconnected for good, by an owner or admin only.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"},{"name":"connectionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/shared-connections":{"get":{"summary":"Everything you share with a workspace, and the calls made through each [read]","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["shared"],"properties":{"shared":{"type":"array","items":{"type":"object","properties":{"connection_id":{"type":"string"},"app":{"type":"string"},"app_name":{"type":"string"},"label":{"type":"string"},"workspace":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"shared_at":{"type":"string","format":"date-time"},"use_count":{"type":"integer"},"uses":{"type":"array","items":{"type":"object","properties":{"session_id":{"type":"string"},"started_by":{"type":"object","properties":{"user_id":{"type":"string"},"name":{"type":"string","nullable":true}}},"key":{"type":"object","nullable":true,"description":"The workspace key that started the session, when one did.","properties":{"id":{"type":"string"},"name":{"type":"string"}}},"method":{"type":"string"},"host":{"type":"string"},"status":{"type":"integer"},"at":{"type":"string","format":"date-time"}}}}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/keys":{"get":{"summary":"Keys that belong to the workspace [read, owner or admin]","description":"A workspace key belongs to the workspace, not to the person who made it, and keeps working after they leave. It acts through the workspace owner's account, whose wallet pays for the sessions it starts, and reaches only the workspace's agents, sessions, files, skills and environments. The listing never carries a secret.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["keys"],"properties":{"keys":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceKey"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Make a workspace key [admin, owner or admin]","description":"The secret is returned only in this response. The key carries no more scope than the credential that makes it.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","scopes"],"properties":{"name":{"type":"string","maxLength":80},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","admin"]}},"expires_at":{"type":"string","format":"date-time","nullable":true}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["key","secret"],"properties":{"key":{"$ref":"#/components/schemas/WorkspaceKey"},"secret":{"type":"string"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/keys/{keyId}":{"delete":{"summary":"Revoke a workspace key [admin, owner or admin]","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"},{"name":"keyId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/hooks":{"get":{"summary":"Get workspace shared hooks [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"hooks":{"type":"array"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"put":{"summary":"Replace workspace shared hooks (owner only) [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"hooks":{"type":"array"}},"required":["hooks"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"hooks":{"type":"array"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/policies":{"get":{"summary":"List workspace policy rules [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"rules":{"type":"array","items":{"$ref":"#/components/schemas/PolicyRule"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Create a workspace policy rule (owner only) [write]","description":"A rule {name, kind: \"CAPABILITY\", config: {\"platform.orchestration\": \"deny\"}} stops every session of the workspace from bringing in other agents as helpers (403 hiring_disabled to the agent; helpers it already has can still be listed, collected and stopped), and sessions created afterwards are not told how to hire. Disable or delete the rule to turn hiring back on.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePolicyRule"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"rule":{"$ref":"#/components/schemas/PolicyRule"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/policies/{ruleId}":{"get":{"summary":"Get a workspace policy rule [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"},{"name":"ruleId","in":"path","required":true,"schema":{"type":"string"},"description":"The policy rule id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"rule":{"$ref":"#/components/schemas/PolicyRule"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Update a workspace policy rule (owner only) [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"},{"name":"ruleId","in":"path","required":true,"schema":{"type":"string"},"description":"The policy rule id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchPolicyRule"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"rule":{"$ref":"#/components/schemas/PolicyRule"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete a workspace policy rule (owner only) [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The universe slug"},{"name":"ruleId","in":"path","required":true,"schema":{"type":"string"},"description":"The policy rule id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/agents":{"get":{"summary":"List agents in the resolved universe [read]","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["agents"],"properties":{"agents":{"type":"array","items":{"$ref":"#/components/schemas/AgentSummary"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Create an agent [write]","description":"An agent is a reusable configuration — engine, prompt, capabilities, secrets. Every field is optional: an empty body creates the default pi agent with no built-in capabilities (capabilities are explicit opt-in; unknown ids → 400). The response's `id` (agent_…) is the agent's only address. One agent can run many sessions; creating the agent provisions nothing — session creation provisions the pod by default (POST /v1/sessions supports deferred provisioning). Optional Idempotency-Key safely replays the original 201 response within the same user and universe; changing the body with the same key returns 409 idempotency_conflict. Keys do not expire.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":1,"maxLength":200,"pattern":"^[!-~]+$"},"description":"A unique key for this creation attempt. Preserve the key and body when retrying."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgent"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["agent"],"properties":{"agent":{"$ref":"#/components/schemas/AgentDetail"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/agents/{id}":{"get":{"summary":"Agent detail [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The agent id (agent_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["agent"],"properties":{"agent":{"$ref":"#/components/schemas/AgentDetail"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Update displayName / capabilities / metadata [write]","description":"Omitted fields preserved; capabilities replaced whole (explicit [] revokes all; effective on the next capability call, no restart); metadata key-merged (null deletes a key); optional expectedVersion → 409 version_conflict on mismatch.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The agent id (agent_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchAgent"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["agent"],"properties":{"agent":{"$ref":"#/components/schemas/AgentDetail"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete the agent — only with zero sessions (409 agent_has_sessions) [admin]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The agent id (agent_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/agents/{id}/archive":{"post":{"summary":"Archive the agent — read-only, sessions keep running, new sessions rejected [admin]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The agent id (agent_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["agent"],"properties":{"agent":{"$ref":"#/components/schemas/AgentDetail"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/agents/{id}/prompt":{"put":{"summary":"Save the user prompt layer; applies to sessions started after the save [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The agent id (agent_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutPrompt"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptUpdateResult"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/agents/{id}/prompt/versions":{"get":{"summary":"Prompt version history [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The agent id (agent_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["versions"],"properties":{"versions":{"type":"array","items":{"$ref":"#/components/schemas/PromptVersion"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/agents/{id}/secrets":{"get":{"summary":"Declared secret keys + set/unset — never values [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The agent id (agent_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["secrets"],"properties":{"secrets":{"type":"array","items":{"$ref":"#/components/schemas/SecretKey"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/agents/{id}/secrets/{key}":{"put":{"summary":"Set a declared secret's value (write-only) [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The agent id (agent_…)"},{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutSecret"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Unset a secret [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The agent id (agent_…)"},{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/external_accounts":{"get":{"summary":"List the workspace's accounts at outside vendors — never credentials [read]","description":"Vendor accounts connected here, and the workspace's model plans (managed under /model-subscriptions; their ids start with `plan:`). `vendors` lists the vendors an account can be connected for and whether connecting takes one `key` or the vendor's full `settings`. 404 where external accounts are not turned on for the workspace.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["external_accounts","vendors"],"properties":{"external_accounts":{"type":"array","items":{"type":"object","required":["id","kind","vendor","vendor_name","label","status","plan","agents","last_used_at","created_at"],"properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["model_subscription","vendor_account"]},"vendor":{"type":"string"},"vendor_name":{"type":"string"},"label":{"type":"string"},"status":{"type":"string","enum":["active","needs_reconnect","exhausted"]},"plan":{"type":["string","null"],"description":"The plan the vendor reported, when it reports one"},"agents":{"type":"array","description":"The agents that have run on it","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}},"last_used_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}}},"vendors":{"type":"array","items":{"type":"object","required":["id","name","credential"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"credential":{"type":"string","enum":["key","settings"]}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Connect a vendor account, or replace the credential of the one with the same vendor and label [write]","description":"The credential is write-only. Every task of the workspace waiting on this vendor's account (an open `connect_account` request) then continues. 422 `invalid_credential` when the vendor does not accept it; 503 `not_migrated` before the store exists. A vendor's own browser sign-in is not offered here.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["vendor","credential"],"properties":{"vendor":{"type":"string","description":"A vendor id from `vendors`"},"label":{"type":"string","description":"Defaults to the vendor's name"},"credential":{"description":"One key, or the vendor's account settings as upper-case names with text values","oneOf":[{"type":"string"},{"type":"object","additionalProperties":{"type":"string"}}]}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["external_account"],"properties":{"external_account":{"type":"object","required":["id","kind","vendor","vendor_name","label","status","plan","agents","last_used_at","created_at"],"properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["model_subscription","vendor_account"]},"vendor":{"type":"string"},"vendor_name":{"type":"string"},"label":{"type":"string"},"status":{"type":"string","enum":["active","needs_reconnect","exhausted"]},"plan":{"type":["string","null"],"description":"The plan the vendor reported, when it reports one"},"agents":{"type":"array","description":"The agents that have run on it","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}},"last_used_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/external_accounts/{id}":{"delete":{"summary":"Disconnect an account; a later task that needs it asks for it again [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The account's id from the list"}],"responses":{"204":{"description":"Disconnected"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/external_accounts/{id}/usage":{"get":{"summary":"Which agents and tasks ran on a vendor account [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The account's id from the list"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["usage"],"properties":{"usage":{"type":"object","required":["agents","tasks"],"properties":{"agents":{"type":"array","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}},"tasks":{"type":"array","items":{"type":"object","required":["session_id","agent_id","title","first_used_at","last_used_at"],"properties":{"session_id":{"type":"string"},"agent_id":{"type":["string","null"]},"title":{"type":["string","null"]},"first_used_at":{"type":"string","format":"date-time"},"last_used_at":{"type":"string","format":"date-time"}}}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/model-subscriptions":{"get":{"summary":"List connected model subscriptions — metadata only, never credentials [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"accounts","in":"query","schema":{"type":"string","enum":["all"]},"description":"Include additional accounts; omitted preserves the legacy provider-only list"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["modelSubscriptions"],"properties":{"modelSubscriptions":{"type":"array","items":{"$ref":"#/components/schemas/ModelSubscription"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Add a separate subscription account [write]","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddModelSubscription"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["modelSubscription"],"properties":{"modelSubscription":{"$ref":"#/components/schemas/ModelSubscription"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/model-subscriptions/{provider}":{"put":{"summary":"Connect or replace a subscription credential (write-only) [write]","description":"anthropic: the sk-ant-oat… token from `claude setup-token`. openai: the contents of ~/.codex/auth.json from `codex login`. cursor: a Cursor API key, or the sign-in file ~/.config/cursor/auth.json from `cursor-agent login`. xai: the sign-in file ~/.grok/auth.json from `grok login`. meta: the sign-in file ~/.config/muse/auth.json from `muse login`. Eligible agents can then run at $0 model usage; with useForNewAgents (default on), new eligible Claude, ChatGPT, Grok and Muse agents use it automatically. Cursor agents use it only when created or switched with modelBilling `account`.","security":[{"bearerAuth":[]}],"parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","enum":["anthropic","openai","cursor","xai","meta"]},"description":"anthropic = Claude subscription · openai = ChatGPT plan · cursor = Cursor plan · xai = Grok subscription · meta = Muse subscription"},{"name":"accountId","in":"query","schema":{"type":"string"},"description":"Target an additional account; omitted targets the legacy provider account"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutModelSubscription"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["modelSubscription"],"properties":{"modelSubscription":{"$ref":"#/components/schemas/ModelSubscription"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Update useForNewAgents / label [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","enum":["anthropic","openai","cursor","xai","meta"]},"description":"anthropic = Claude subscription · openai = ChatGPT plan · cursor = Cursor plan · xai = Grok subscription · meta = Muse subscription"},{"name":"accountId","in":"query","schema":{"type":"string"},"description":"Target an additional account; omitted targets the legacy provider account"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchModelSubscription"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["modelSubscription"],"properties":{"modelSubscription":{"$ref":"#/components/schemas/ModelSubscription"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Disconnect — affected agents keep their pointer and fail until reconnected or switched [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","enum":["anthropic","openai","cursor","xai","meta"]},"description":"anthropic = Claude subscription · openai = ChatGPT plan · cursor = Cursor plan · xai = Grok subscription · meta = Muse subscription"},{"name":"accountId","in":"query","schema":{"type":"string"},"description":"Target an additional account; omitted targets the legacy provider account"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"affectedAgents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"agentId":{"type":["string","null"]},"name":{"type":"string"}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/skills":{"get":{"summary":"List skills in the resolved universe [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":100}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["skills"],"properties":{"skills":{"type":"array","items":{"$ref":"#/components/schemas/Skill"}},"nextCursor":{"type":["string","null"]}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Create a skill (uploads revision 1) [write]","description":"A skill is a universe-scoped, immutably-revisioned file bundle agents load on demand (RFC-0073). Attach it to agents via the `skills` array on create/patch.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["files"],"properties":{"files":{"type":"array","items":{"type":"string","format":"binary"},"description":"One zip archive or individual files. SKILL.md with `name` + `description` frontmatter must sit at the root of the single top-level directory. ≤30 MB uncompressed; zip entries keep their unix exec bit."},"displayName":{"type":"string","maxLength":255}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["skill","revision"],"properties":{"skill":{"$ref":"#/components/schemas/Skill"},"revision":{"$ref":"#/components/schemas/SkillRevision"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/skills/{skillId}":{"get":{"summary":"Skill detail [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string"},"description":"The skill id (skill_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["skill"],"properties":{"skill":{"$ref":"#/components/schemas/Skill"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Make a skill always available, or stop [write]","description":"With `attachByDefault: true`, every session created in the workspace from then on is provisioned with the skill's latest revision, unless the session is created with `defaults: \"none\"`. Sessions of agents that cannot take skills start without it.","security":[{"bearerAuth":[]}],"parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string"},"description":"The skill id (skill_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["attachByDefault"],"properties":{"attachByDefault":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["skill"],"properties":{"skill":{"$ref":"#/components/schemas/Skill"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete a skill and all its revisions [write]","description":"409 skill_in_use while any agent references the skill.","security":[{"bearerAuth":[]}],"parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string"},"description":"The skill id (skill_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/skills/{skillId}/revisions":{"get":{"summary":"List a skill's revisions, newest first [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string"},"description":"The skill id (skill_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["revisions"],"properties":{"revisions":{"type":"array","items":{"$ref":"#/components/schemas/SkillRevision"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Create a revision — a complete snapshot [write]","description":"Omitted files are not carried over. The new SKILL.md name must match the skill's name (400 name_mismatch).","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["files"],"properties":{"files":{"type":"array","items":{"type":"string","format":"binary"},"description":"One zip archive or individual files. SKILL.md with `name` + `description` frontmatter must sit at the root of the single top-level directory. ≤30 MB uncompressed; zip entries keep their unix exec bit."},"displayName":{"type":"string","maxLength":255}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["revision"],"properties":{"revision":{"$ref":"#/components/schemas/SkillRevision"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/skills/{skillId}/revisions/{revisionId}":{"get":{"summary":"Skill revision detail (metadata + file manifest) [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string"},"description":"The skill id (skill_…)"},{"name":"revisionId","in":"path","required":true,"schema":{"type":"string"},"description":"The skill revision id (skr_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["revision"],"properties":{"revision":{"$ref":"#/components/schemas/SkillRevision"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete one revision [write]","description":"400 last_revision for a skill's only revision; 409 revision_in_use while pinned by an agent; deleting the latest repoints latestRevisionId.","security":[{"bearerAuth":[]}],"parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string"},"description":"The skill id (skill_…)"},{"name":"revisionId","in":"path","required":true,"schema":{"type":"string"},"description":"The skill revision id (skr_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/skills/{skillId}/revisions/{revisionId}/content":{"get":{"summary":"Read a UTF-8 skill file [read]","description":"Reads only a file in the authorized immutable revision. Binary files return 415; absent files return 404. Responses are not cached.","security":[{"bearerAuth":[]}],"parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string"},"description":"The skill id (skill_…)"},{"name":"revisionId","in":"path","required":true,"schema":{"type":"string"},"description":"The skill revision id (skr_…)"},{"name":"path","in":"query","required":true,"schema":{"type":"string"},"description":"Exact relative file path, such as SKILL.md"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["path","content"],"properties":{"path":{"type":"string"},"content":{"type":"string"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions":{"get":{"summary":"List sessions; ?agent= filters to one spec [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"agent","in":"query","schema":{"type":"string"},"description":"The agent id (agent_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["sessions"],"properties":{"sessions":{"type":"array","items":{"$ref":"#/components/schemas/Session"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Create a session — starts provisioning by default; optionally defer until the first turn [write]","description":"Optional llm and reasoningEffort override the agent's defaults for this session before billing selection or provisioning. A model must be current for the agent's harness; omitted or null reasoningEffort inherits the agent's setting normalized for the target model. Explicit effort must fit both harness and target model. A non-empty initial_events list (user.message only, all-or-nothing) starts the first turn in the same call and provisions in either mode. Without initial events, provision: \"deferred\" skips the boot: the session reads idle with no pod and costs nothing until its first turn — for a session that waits on a gate or a schedule. Machine shape (vcpus/memoryMb) is per-session.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSession"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["session"],"properties":{"session":{"$ref":"#/components/schemas/Session"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}":{"get":{"summary":"Session detail — status is provisioning (sandbox booting or installing packages) | idle | running | terminated [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["session"],"properties":{"session":{"$ref":"#/components/schemas/Session"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Update title / metadata / model / reasoning effort / billing / budget [write]","description":"llm and reasoningEffort are session settings: they change this session only, never the agent or its other sessions. The model must fit the harness; explicit effort must fit both harness and target model. Inherited effort is normalized for that model. An idle session restarts its engine in place; a running session finishes its turn and applies the change at the next turn (the response is 200 either way). A parked session applies it at its next wake.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchSession"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["session"],"properties":{"session":{"$ref":"#/components/schemas/Session"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Retire a Session and tear down its runtime [write]","description":"Marks the Session deleted and removes operational bindings; durable transcripts and accounting records are retained. GET Session answers 404 afterward. Active execution must stop before cleanup. Works on idle and archived Sessions.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/access":{"get":{"summary":"Who may use the session, and what you are to it [read]","description":"Members of the session's workspace may read and prompt a workspace session; a private session is the owner's alone. People whose verified email is listed may read its message history from any workspace. Viewer emails are returned to the owner only.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionAccess"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Make the session private or workspace-visible, and edit its viewers [write, owner]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"visibility":{"type":"string","enum":["workspace","private"]},"add_viewers":{"type":"array","items":{"type":"string"},"maxItems":100},"remove_viewers":{"type":"array","items":{"type":"string"},"maxItems":100}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionAccess"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/shared-sessions":{"get":{"summary":"Sessions other people shared with you to read, newest first [read]","description":"Viewing is a person's access, so a credential limited to one workspace lists none. A limit that is not an integer from 1 to 100, or a cursor that is not valid, is 400 invalid_request.","security":[{"bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"next_cursor from the previous page"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["sessions","next_cursor"],"properties":{"sessions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string","nullable":true},"agent_type":{"type":"string"},"owner":{"type":"object","properties":{"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true}}},"workspace":{"type":"object","properties":{"name":{"type":"string"}}},"shared_at":{"type":"string","format":"date-time"}}}},"next_cursor":{"type":"string","nullable":true,"description":"Pass back as ?cursor= for the next page; null on the last page"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/share":{"get":{"summary":"The session's share link, or {\"token\": null} when sharing is off (owner only) [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionShareLink"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Turn sharing on and get the share link — idempotent; {\"access\": \"view\"} asks for a view-only link; {\"rotate\": true} replaces it [write]","description":"A guest link (access prompt, the default) has a shareUrl that opens the session's guest page for anyone holding it, with no account; turns sent through it bill the session's owner. A view-only link (access view) has no shareUrl: anyone holding its token reads the conversation's text at GET /links/{token}/events and can do nothing else. A session has one link; asking for the other access level replaces it with a new token, so the old URL dies. Rotating keeps the level and kills the old URL immediately; rotate cannot be combined with access.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"rotate":{"type":"boolean","default":false},"access":{"type":"string","enum":["prompt","view"],"default":"prompt"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionShareLink"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Turn sharing off — the link stops working immediately [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/links/{token}/events":{"get":{"summary":"Read the conversation a share link opens, as any signed-in caller holding the link","description":"Answers the session as its reader sees it and one page of people's turns and the agent's replies, text only (no attachments, tool calls, system messages or marks), oldest first, with the same opaque cursor as /sessions/{id}/events. Works for view-only and guest links. Unknown, rotated, disabled and deleted links all answer 404 not_found; reads are rate-limited per token (429 rate_limited with Retry-After). Needs a token with read scope from any workspace; the link is the grant, so the caller need not belong to the session's workspace.","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"cursor from the previous page"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["session","events","cursor","hasMore"],"properties":{"session":{"type":"object","required":["id","title","agent_type","owner","workspace"],"properties":{"id":{"type":"string"},"title":{"type":"string","nullable":true},"agent_type":{"type":"string"},"owner":{"type":"object","properties":{"name":{"type":"string","nullable":true}}},"workspace":{"type":"object","properties":{"name":{"type":"string"}}}}},"events":{"type":"array","items":{"type":"object"},"description":"user.message and agent.message events, text parts only"},"cursor":{"type":"string","nullable":true},"hasMore":{"type":"boolean"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/archive":{"post":{"summary":"Archive the session — irreversible; blocks new events, history stays readable [write]","description":"Durably marks archived=true and sets status to terminated, tears down the pod and stored context, and refuses further messages (400 session_archived); the record and its events remain readable. A running session is refused with 400 session_running: interrupt and wait for idle first. A changed active Session whose archive mark did not commit returns 409 session_changed. Idempotent when another request already archived it.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["session"],"properties":{"session":{"$ref":"#/components/schemas/Session"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/messages":{"post":{"deprecated":true,"summary":"Deprecated — use POST /sessions/{id}/events [write]","description":"The legacy input shape ({parts}); accepted for one release and translated to a single user.message, then 410. Optional Idempotency-Key header dedupes retries.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessages"}}}},"responses":{"202":{"description":"Accepted — body is {}; output arrives on the stream","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/events":{"post":{"summary":"Send events — the one input: user.message, user.interrupt, system.message [write]","description":"The conversation plane (edge-routed to the chat-proxy). Body {events: [...]} (1–50), optionally requireIdle: true for one user.message (and optional trailing system.message). Exclusive admission refuses a busy session with 409 before persisting or delivering the message; a successful echo's user id names the admitted run. Its admission field is created only when this POST committed the exclusive input; an idempotent replay returns replayed. This field is not part of history or SSE. This is a Session admission receipt, not proof that another client's earlier queued joined input has finished on the Pod. Ordinary sends may join an open run. validated all-or-nothing. A user.message carries content blocks: text, image and document with base64 / url / file sources (inline base64 ≤ 20 MiB per request; larger content goes through POST /files). A system.message (text only) must be last and follow the user.message it accompanies: privileged context for that turn and, through the agent's transcript, later turns. user.interrupt stops the in-flight turn; with mode: \"save\" it instead asks the run to start no new work, save what it has (files plus a progress note in the working directory) and end its turn with a reply listing what was saved, and stops it only if it is still running after a 10 minute grace window (echo status saving, or no_turn when nothing is running). A later user.message continues in the same session. Every event echoes back in the history shape with a stable id; sources are echoed as file sources naming per-session copies (never base64). Optional Idempotency-Key header: a replay returns the original echo. 402 insufficient_credits / budget_reached, 503 egress_policy_failed, 400 session_archived refuse the whole request before any row is written.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEvents"}}}},"responses":{"200":{"description":"OK — one echo per event, in order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEventsResult"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"get":{"summary":"The event history — the same event objects the stream delivers [read]","description":"The session's history, one event per message: user.message and system.message (with content), agent.message (with parts), user.interrupt, and the turn marks session.status_running, session.status_idle (stop_reason.type is end_turn, retries_exhausted, provider_lost or budget_reached) and session.error. agent.reasoning, agent.tool_use, agent.tool_result and agent.status appear on the live stream only, not in history. Oldest-first with an opaque numeric cursor. Reconnect = open the stream, list events, dedupe by event id. types[] filters (e.g. types[]=user.message&types[]=agent.message is the transcript view).","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":500}},{"name":"types[]","in":"query","schema":{"type":"array","items":{"type":"string"}}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventsPage"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/stream":{"get":{"summary":"The standing event stream (SSE) [read]","description":"text/event-stream, stays open across turns. If a run is in flight when the stream opens, its status marks so far (session.status_running, session.error, user.interrupt) are replayed from history under their own ids and timestamps, so a stream opened mid-run still sees the boundary its duration is measured from; a run that has already ended is not replayed — read it from the event history. Everything else is live. Dedupe by event id. Events: agent.message, agent.reasoning, agent.tool_use, agent.tool_result, agent.status, session.status_running, session.status_idle (carries stop_reason — never break on bare idle), session.error (the stream stays open; an idle follows), user.interrupt, session.status_terminated (terminal), session.deleted (terminal). User messages are not sent on the live stream — they appear in the event history only. Reconnect = reopen + list events + dedupe by event id.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"SSE stream","content":{"text/event-stream":{}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/interrupt":{"post":{"summary":"Abort the in-flight turn [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterruptResult"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/usage":{"get":{"summary":"The session's billed usage, newest first [read]","description":"Totals plus one row per billed event — model turns, runtime, capability and connector calls — with the token breakdown, list and billed dollars, basis and duration. `limit` (default 50) pages with an opaque `cursor`; keep following `cursor` until it is null. A row whose `coveredBy` is `subscription` ran on the reader's own Claude or ChatGPT plan: `listCostUsd` is what it was worth, `billedCostUsd` is zero. Dollar amounts here are numbers in USD, not the `{amount, currency}` cents object used elsewhere.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"A cursor from a previous page"},{"name":"limit","in":"query","schema":{"type":"integer"},"description":"1–500, default 50"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionUsage"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/policies":{"get":{"summary":"List session-level policy rules [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"rules":{"type":"array","items":{"$ref":"#/components/schemas/PolicyRule"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Create a session-level policy rule (owner only) [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePolicyRule"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"rule":{"$ref":"#/components/schemas/PolicyRule"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/policies/{ruleId}":{"get":{"summary":"Get a session-level policy rule [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"ruleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"rule":{"$ref":"#/components/schemas/PolicyRule"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Update a session-level policy rule (owner only) [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"ruleId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchPolicyRule"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"rule":{"$ref":"#/components/schemas/PolicyRule"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete a session-level policy rule (owner only) [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"ruleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/effective-policy":{"get":{"summary":"Effective merged policy for a session across all layers [read]","description":"Returns all policy rules for workspace → agent → session, with a note when native tool policies prevent an unsupported runtime from starting.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"rules":{"type":"array","items":{"$ref":"#/components/schemas/PolicyRule"}},"note":{"type":"string"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/studio":{"post":{"deprecated":true,"summary":"Deprecated: the address of the web app running inside the session's pod [write]","description":"Replaced by `PUT /sessions/{id}/ports/{port}` and `POST …/ports/{port}/grants`; kept for one release while the consumer app moves. Minted once per session and stable afterwards. `port` is what the app inside the pod listens on — 1024–65535, defaulting to the studio's own port. An archived session answers 400 session_archived.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStudioRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStudio"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/desktop/machines":{"get":{"summary":"The person's Macs connected through the Mac app [read]","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesktopMachineList"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Register this Mac [write]","description":"The Mac app registers the Mac it runs on and is handed its connect token once. The token is what the app polls the relay with; the person's own token never reaches the app. Edge-routed to the chat-proxy like the ports routes.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesktopMachineRequest"}}}},"responses":{"201":{"description":"Registered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesktopMachineCreated"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/desktop/machines/{id}":{"delete":{"summary":"Revoke a Mac [write]","description":"The app's connect token stops working and every folder it handed over answers 404 from then on.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Revoked"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/desktop/machines/{id}/mounts":{"post":{"summary":"Hand a locally selected folder on that Mac to agents [machine connect token]","description":"Answers the address a spec's `mcp_servers` entry carries (`{type: \"url\", name: \"this-mac\", url: mcp_url}`): a pod's MCP calls on it are relayed to the Mac app, which answers them with file tools rooted at the folder and holds every change for the person's confirmation. This route accepts only that Mac's connect token after its native picker returns a normalized absolute path; an account token cannot create a mount. A Mac that is not polling answers 503 machine_offline to the pod.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesktopMountRequest"}}}},"responses":{"201":{"description":"Mounted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesktopMount"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/desktop/mounts/{id}":{"delete":{"summary":"Take a folder back [write]","description":"Its address answers 404 from then on; a running session keeps its spec entry but every call to it fails.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Revoked"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/desktop/mounts/{id}/verify":{"post":{"summary":"Verify a live folder mount before starting agents [read]","description":"Confirms that the mount id and capability URL still name the same live folder owned by this account in the token's universe, or the account's personal universe when the token is unscoped. A stale, revoked, foreign-universe or mismatched mount answers 404.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesktopMountVerifyRequest"}}}},"responses":{"204":{"description":"The mount is live and owned by this account"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/ports":{"get":{"summary":"The session's exposed ports, oldest first [read]","description":"Every local server the agent runs inside the pod that has been exposed on an origin of its own.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPortList"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/ports/{port}":{"put":{"summary":"Expose a port the agent's local server listens on [write]","description":"Create-or-get: the port gets a stable origin `https://app-<id>.agentsky.dev/` relayed to the pod (HTTP and WebSocket) while the pod runs; calling again returns the same record, and a `visibility` in the body replaces the stored one in place. `port` is 1024–65535 and never the pod's own (400 invalid_request). A private port (the default) admits a browser only through an entry link from `POST …/grants`; a public port admits anyone with the address. A parked pod answers a paused page and is never woken by a visit. An archived session answers 400 session_archived.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"port","in":"path","required":true,"schema":{"type":"integer","minimum":1024,"maximum":65535},"description":"The port the app listens on inside the pod"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPortRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPort"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"get":{"summary":"One exposed port [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"port","in":"path","required":true,"schema":{"type":"integer","minimum":1024,"maximum":65535},"description":"The port the app listens on inside the pod"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPort"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Stop exposing a port [write]","description":"The origin answers 404 from then on (within a few seconds); browsers that had entered are signed out with it.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"port","in":"path","required":true,"schema":{"type":"integer","minimum":1024,"maximum":65535},"description":"The port the app listens on inside the pod"}],"responses":{"204":{"description":"Revoked"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/ports/{port}/grants":{"post":{"summary":"An entry link for an exposed port [write]","description":"For a private port: a single-use link, good for a minute, that signs the browser opening it in to the port's origin (a cookie that lives twelve hours) and lands on `path`; minting again supersedes the previous unused link. For a public port: the plain address. An archived session answers 400 session_archived.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"port","in":"path","required":true,"schema":{"type":"integer","minimum":1024,"maximum":65535},"description":"The port the app listens on inside the pod"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPortGrantRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPortGrant"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/harness":{"get":{"summary":"Remote-harness relay WebSocket [write]","description":"WebSocket (Upgrade: websocket) served by the chat-proxy. The maker's ACP process connects with `Authorization: Bearer hct_…` (the per-harness connect token minted via `POST /harnesses/{id}/connect-token`). The relay validates the token, then opens a parallel WebSocket to the session's pod and splices both connections together, forwarding newline-delimited JSON-RPC frames in both directions. One live connection per session; a second attempt while one is open returns 409. The session must be ACTIVE and the pod RUNNING. Gated by the `REMOTE_HARNESSES` platform switch (off → 404).","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"101":{"description":"Switching Protocols — WebSocket relay open"},"401":{"description":"Missing or invalid connect token"},"403":{"description":"Token does not belong to this session's harness"},"404":{"description":"Session not found or REMOTE_HARNESSES gate is off"},"409":{"description":"Session not active, pod not ready, or relay already connected"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/workspace/files":{"get":{"summary":"List a directory in the session's workspace [read]","description":"Returns up to 200 entries (name, type, size, mtime) for a directory under /data/workspace. Dotfiles are excluded by default; pass ?hidden=true to include them. Only regular files and directories are listed: symlinks, FIFOs, sockets and devices never are. Paths are confined to the workspace root; '..' and absolute paths outside the root return 400 invalid_path. A parked or suspended pod returns 409 session_parked — send a message to wake it.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"path","in":"query","schema":{"type":"string"},"description":"Relative or absolute path under workspace root; defaults to root"},{"name":"hidden","in":"query","schema":{"type":"boolean"},"description":"Include dotfiles (default false)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"path":{"type":"string"},"entries":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["file","directory"]},"size":{"type":"integer"},"mtime":{"type":"string","format":"date-time"}}}},"truncated":{"type":"boolean"},"limit":{"type":"integer"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/workspace/files/content":{"get":{"summary":"Download a file from the session's workspace [read]","description":"Returns the raw file bytes as an attachment. Limited to 1 MB. Binary files are supported. Content-Type is inferred from the file extension. Returns 400 not_a_file for directories, 413 file_too_large when over the cap, 403 path_escape for symlink escapes, 409 session_parked when the pod is not running.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"path","in":"query","required":true,"schema":{"type":"string"},"description":"Relative or absolute path to the file under workspace root"}],"responses":{"200":{"description":"File contents","headers":{"Content-Disposition":{"schema":{"type":"string"}},"Content-Type":{"schema":{"type":"string"}}},"content":{"*/*":{"schema":{"type":"string","format":"binary"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/workspace/changes":{"get":{"summary":"Git status and diff summary for each repo in the session's workspace [read]","description":"Finds up to 10 git repositories within three levels of the workspace root and, for each, runs `git status --porcelain=v1` and `git diff --stat HEAD` inside the pod as the workspace owner, with fsmonitor, hooks, external diff drivers and textconv disabled. Each output is bounded to 200 lines. `repos` is empty when the workspace has no repository. Never wakes the pod: 409 session_parked when it is not running, 409 workspace_unsupported when its runtime has no exec or resumes a parked sandbox on contact (E2B), 503 workspace_unavailable when the read cannot run as the workspace owner.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"root":{"type":"string"},"repos":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","description":"repo directory relative to root; \".\" for the root itself"},"status":{"type":["string","null"],"description":"git status --porcelain=v1 output; null when clean"},"stat":{"type":["string","null"],"description":"git diff --stat HEAD output; null when no diff or no commit yet"}}}},"limit":{"type":"integer","description":"most repos reported"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/workspace/import":{"post":{"summary":"Copy a folder from the caller's machine into the workspace [write]","description":"The body is the folder as a gzipped tar (up to 25 MB). It is unpacked at <workspace root>/<name> as the workspace owner and made a git repository whose first commit is that copy, so /workspace/patch later answers the work done on it. Wakes a parked pod. 400 invalid_name, 409 already_exists, 413 archive_too_large, 422 invalid_archive.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"name","in":"query","required":true,"schema":{"type":"string"},"description":"the folder's name in the workspace: 1–80 letters, digits, spaces, dots, dashes or underscores"}],"requestBody":{"required":true,"content":{"application/gzip":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"path":{"type":"string"},"files":{"type":"integer"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/workspace/patch":{"post":{"summary":"The work in one workspace repo since its base branch, as a git patch [write]","description":"Runs inside the pod as the workspace owner and returns one binary-safe `git diff --binary` from the merge base of HEAD with the branch's upstream (or the remote's default branch, or else the base an imported folder recorded, with base_branch \"\") to the working tree: commits, uncommitted edits and new files that are not ignored. The repository's own index is left as it was. Wakes a parked pod. 400 not_a_repository, 409 no_base when there is no remote branch to compare against, 413 patch_too_large over 5 MB.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["repo"],"properties":{"repo":{"type":"string","description":"repo directory relative to the workspace root, as /workspace/changes lists it; \".\" for the root"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"repo":{"type":"string"},"base_branch":{"type":"string","description":"the branch the work started from, as the remote names it"},"base_commit":{"type":"string","description":"the commit the patch applies to"},"commits":{"type":"array","items":{"type":"string"},"description":"subjects of the commits since the base, oldest first"},"patch":{"type":"string","description":"base64 of the patch; empty when nothing changed"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/routines":{"get":{"summary":"List routines [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer"},"description":"1–500, default 50"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Routine"}},"cursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Create a routine — scheduled agent execution [write]","description":"initial_events (1–50 user.message events) are delivered on every fire. target picks the mode: new_session creates a fresh session per run; session sends the turn into an existing session (busy target → failed run session_busy_error). schedule is a 5-field POSIX cron with an IANA timezone; omit it for a manual-run-only routine. budget bounds each run separately.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRoutine"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["routine"],"properties":{"routine":{"$ref":"#/components/schemas/Routine"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/routines/{id}":{"get":{"summary":"Routine detail [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["routine"],"properties":{"routine":{"$ref":"#/components/schemas/Routine"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Update a routine — omit preserves; null clears schedule/budget [write]","description":"initial_events is a full replacement; metadata is key-patched (null deletes a key); name and target cannot be cleared. Archived routines are immutable (409).","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchRoutine"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["routine"],"properties":{"routine":{"$ref":"#/components/schemas/Routine"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/routines/{id}/pause":{"post":{"summary":"Pause — suppress scheduled fires; manual runs still work [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["routine"],"properties":{"routine":{"$ref":"#/components/schemas/Routine"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/routines/{id}/unpause":{"post":{"summary":"Unpause — resumes from the NEXT occurrence; missed fires are never backfilled [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["routine"],"properties":{"routine":{"$ref":"#/components/schemas/Routine"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/routines/{id}/archive":{"post":{"summary":"Archive — terminal; the schedule stops and the routine becomes immutable [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["routine"],"properties":{"routine":{"$ref":"#/components/schemas/Routine"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/routines/{id}/run":{"post":{"summary":"Run now, outside the schedule; works while paused [write]","description":"With no body it is a manual run: trigger_context {type:\"manual\"}. With `input` or `idempotency_key` it is an API-triggered run: trigger_context {type:\"api\"}; the input is added to the run's first message under the label \"Input for this run:\", and a repeated idempotency_key on the same routine returns the first run instead of starting another. Neither emits routine_run webhooks.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"input":{"type":"string","maxLength":50000,"description":"What this run should work on, such as an event's payload"},"idempotency_key":{"type":"string","maxLength":200,"description":"The caller's id for the event; a repeat returns the first run"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["run"],"properties":{"run":{"$ref":"#/components/schemas/RoutineRun"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/routines/{id}/inbound-url":{"get":{"summary":"Whether the routine has an inbound URL [read]","description":"`inbound_url` is null when there is none. The URL itself is never returned here, only the start of its secret.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"inbound_url":{"oneOf":[{"type":"object","properties":{"routine_id":{"type":"string"},"prefix":{"type":"string","description":"The start of the secret in the URL"},"created_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"}},"required":["routine_id","prefix","created_at","last_used_at"]},{"type":"null"}]}},"required":["inbound_url"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Make the routine's inbound URL [write]","description":"Returns a URL that starts a run of this routine when posted to, with no API token: for a service that can only call a URL. It replaces any earlier one, which stops working at once. The URL carries its own secret and is returned only in this response.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"inbound_url":{"type":"object","properties":{"routine_id":{"type":"string"},"prefix":{"type":"string","description":"The start of the secret in the URL"},"created_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"},"url":{"type":"string"}},"required":["routine_id","prefix","created_at","last_used_at","url"]}},"required":["inbound_url"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Remove the routine's inbound URL [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"removed":{"type":"boolean"}},"required":["removed"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/routines/{id}/result-email":{"get":{"summary":"Whether the routine emails its result [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"result_email":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"]}},"required":["result_email"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"put":{"summary":"Email the routine's creator the result of each run [write]","description":"When a run finishes, its creator gets one email with the last thing the agent said and a link to the run. It is sent whatever the person chose for finished-task emails, and every email carries a link that turns this routine's emails off. Only a routine whose target is `new_session` can have it (400 otherwise); an archived routine answers 409.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"result_email":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"]}},"required":["result_email"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Stop emailing the routine's result [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"result_email":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"]}},"required":["result_email"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/routines/{id}/precheck":{"get":{"summary":"The routine's precheck [read]","description":"`precheck` is null when there is none. It carries what the last check before a scheduled fire found.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"precheck":{"oneOf":[{"type":"object","properties":{"routine_id":{"type":"string"},"url":{"type":"string"},"created_at":{"type":"string"},"last_checked_at":{"type":["string","null"],"description":"When the URL was last checked before a scheduled fire"},"last_result":{"type":["string","null"],"enum":["changed","unchanged","failed",null],"description":"changed: the fire ran. unchanged: the fire was skipped. failed: the check could not be completed and the fire ran anyway."},"last_error":{"type":["object","null"],"description":"{type, message} when last_result is failed. Types: address_not_allowed · dns_failed · redirect · http_status · too_large · timeout · network."}},"required":["routine_id","url","created_at","last_checked_at","last_result","last_error"]},{"type":"null"}]}},"required":["precheck"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"put":{"summary":"Run scheduled fires only when a URL's content changed [write]","description":"Before each scheduled fire the platform GETs `url` and compares its content with the content at the last scheduled fire that ran. The same content skips the fire: it is recorded as a run with error.type `precheck_unchanged` and no session, and nothing is charged. New content, and the first check, run the fire. A check that cannot be completed (a redirect, a status outside 2xx, more than 256 KiB, more than 5 seconds, a host that is not on the public internet) never skips: the fire runs and the reason is kept in `last_error`. Manual runs, API runs and inbound-URL runs never consult it. The URL must be https on the default port, with no user name or password, and must not point at a private, loopback or link-local address (400 otherwise); it is fetched with no credentials. Setting a URL forgets what the earlier check remembered. An archived routine answers 409.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"precheck":{"type":"object","properties":{"routine_id":{"type":"string"},"url":{"type":"string"},"created_at":{"type":"string"},"last_checked_at":{"type":["string","null"],"description":"When the URL was last checked before a scheduled fire"},"last_result":{"type":["string","null"],"enum":["changed","unchanged","failed",null],"description":"changed: the fire ran. unchanged: the fire was skipped. failed: the check could not be completed and the fire ran anyway."},"last_error":{"type":["object","null"],"description":"{type, message} when last_result is failed. Types: address_not_allowed · dns_failed · redirect · http_status · too_large · timeout · network."}},"required":["routine_id","url","created_at","last_checked_at","last_result","last_error"]}},"required":["precheck"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Remove the routine's precheck [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"removed":{"type":"boolean"}},"required":["removed"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/routines/{id}/channel-trigger":{"get":{"summary":"The routine's chat trigger [read]","description":"`channel_trigger` is null when there is none. `available` says whether messages of this workspace's connected chats are offered to routines in this deployment; where it is false a trigger can be stored and will never match.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"channel_trigger":{"oneOf":[{"type":"object","properties":{"routine_id":{"type":"string"},"connection_id":{"type":"string"},"thread_id":{"type":["string","null"],"description":"The one conversation whose messages start a run; null for every conversation on the connection"},"text_prefix":{"type":["string","null"],"description":"What a message has to start with to start a run; null for every message"},"created_at":{"type":"string"},"last_matched_at":{"type":["string","null"]}},"required":["routine_id","connection_id","thread_id","text_prefix","created_at","last_matched_at"]},{"type":"null"}]},"available":{"type":"boolean"}},"required":["channel_trigger","available"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"put":{"summary":"Start the routine from a message in a connected chat [write]","description":"A message starts a run when it is on the connection, in `thread_id` when one is given, and starts with `text_prefix` when one is given (leading mentions of the bot and letter case are ignored). Only messages from the person the routine belongs to start a run: the person who connected the chat, or a chat identity they linked to the same account. Anyone else's message is routed as if there were no trigger. The text after the prefix is added to the run's first message under the label \"Input for this run:\". The run is a task of the routine's creator (trigger_context {type:\"channel\", connection_id, thread_id}), and when its turn ends its last message is posted, once, in the conversation the message came from, with a link to the run. A message that started a run is sent nowhere else. One message starts at most one run; when several routines match, the one naming a thread and then the longest prefix wins. A paused or archived routine starts nothing, and more than 30 runs of one routine in a minute are dropped. Only the routine's creator can set the trigger (403 otherwise), on a connected chat of their own in this workspace (404 otherwise). `thread_id` must be a conversation on that connection and `text_prefix` 1 to 200 characters (400 otherwise). Setting a trigger replaces the earlier one. An archived routine answers 409.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"connection_id":{"type":"string"},"thread_id":{"type":"string"},"text_prefix":{"type":"string"}},"required":["connection_id"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"channel_trigger":{"type":"object","properties":{"routine_id":{"type":"string"},"connection_id":{"type":"string"},"thread_id":{"type":["string","null"],"description":"The one conversation whose messages start a run; null for every conversation on the connection"},"text_prefix":{"type":["string","null"],"description":"What a message has to start with to start a run; null for every message"},"created_at":{"type":"string"},"last_matched_at":{"type":["string","null"]}},"required":["routine_id","connection_id","thread_id","text_prefix","created_at","last_matched_at"]}},"required":["channel_trigger"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Remove the routine's chat trigger [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"removed":{"type":"boolean"}},"required":["removed"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/routines/{id}/deliver-to":{"get":{"summary":"Where the routine's runs post their answer [read]","description":"`deliver_to` is null when the answers are posted nowhere.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"deliver_to":{"oneOf":[{"type":"object","properties":{"routine_id":{"type":"string"},"type":{"type":"string","enum":["channel_thread"]},"connection_id":{"type":"string"},"thread_id":{"type":"string"},"created_at":{"type":"string"}},"required":["routine_id","type","connection_id","thread_id","created_at"]},{"type":"null"}]}},"required":["deliver_to"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"put":{"summary":"Post each run's answer to a conversation in a connected chat [write]","description":"When a turn of a run's session ends and the run is not waiting on its owner, the last thing the agent said (at most 3,000 characters) is posted in the conversation with a link to the run, once per run. `thread_id` defaults to the chat itself. A run a chat message started answers where that message was instead. Only the routine's creator can set this (403 otherwise), on a connected chat of their own in this workspace (404 otherwise). An archived routine answers 409.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["channel_thread"]},"connection_id":{"type":"string"},"thread_id":{"type":"string"}},"required":["type","connection_id"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"deliver_to":{"type":"object","properties":{"routine_id":{"type":"string"},"type":{"type":"string","enum":["channel_thread"]},"connection_id":{"type":"string"},"thread_id":{"type":"string"},"created_at":{"type":"string"}},"required":["routine_id","type","connection_id","thread_id","created_at"]}},"required":["deliver_to"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Stop posting the routine's answers to a conversation [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The routine id (rtn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"removed":{"type":"boolean"}},"required":["removed"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/routines/inbound/{token}":{"post":{"summary":"Start a run through the routine's inbound URL","description":"No Authorization header: the secret in the path is the credential. The request body, in any format and up to 50,000 characters, is added to the run's first message under the label \"Input for this run:\"; an empty body starts a run with no input. An `Idempotency-Key` header makes a repeated delivery return the first run. A paused routine answers 409 and starts nothing, an unknown URL or an archived routine answers 404, and more than 30 runs of one routine in a minute answers 429. The run is a task of the routine's owner (trigger_context {type:\"api\"}).","security":[],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"},"description":"The secret part of the inbound URL (rin_…)"},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":200}}],"requestBody":{"required":false,"content":{"*/*":{"schema":{"type":"string","maxLength":50000}}}},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"type":"object","properties":{"run":{"type":"object","properties":{"id":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["id","created_at"]}},"required":["run"]}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/routine-runs":{"get":{"summary":"List routine runs — every fire attempt [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"routine","in":"query","schema":{"type":"string"},"description":"Filter to one routine (rtn_…)"},{"name":"has_error","in":"query","schema":{"type":"boolean"},"description":"true = failed runs, false = runs with a session"},{"name":"trigger_type","in":"query","schema":{"type":"string","enum":["schedule","manual"]}},{"name":"created_at[gte]","in":"query","schema":{"type":"string"},"description":"Also gt / lt / lte"},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/RoutineRun"}},"cursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/routine-runs/{id}":{"get":{"summary":"Routine run detail [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The run id (rrun_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["run"],"properties":{"run":{"$ref":"#/components/schemas/RoutineRun"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/hook_rules":{"get":{"summary":"The workspace's hook rules, in evaluation order [read]","description":"`enabled` says whether hook rules are turned on for the workspace; where they are not the list is empty and nothing is evaluated.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["hook_rules","enabled","can_edit"],"properties":{"enabled":{"type":"boolean","description":"Whether hook rules are turned on for the workspace."},"can_edit":{"type":"boolean","description":"Whether the caller may replace the rules: they are turned on and the caller owns the workspace."},"hook_rules":{"type":"array","items":{"type":"object","required":["id","point","match","action","webhook_id","enabled","created_at","updated_at"],"properties":{"id":{"type":"string","description":"hkr_…"},"point":{"type":"string","enum":["session.start","tool.call","spend","turn.end"]},"match":{"type":"object","additionalProperties":{"type":"string"}},"action":{"type":"string","enum":["notify","block","require_approval"]},"webhook_id":{"type":["string","null"]},"enabled":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"put":{"summary":"Replace the workspace's hook rules (owner only) [write]","description":"The body is the whole ordered list (at most 20); the order is the order of evaluation. A rule sent with the `id` of an existing rule keeps it. Points: `session.start` (a session is about to be created), `tool.call` (a capability call, a call to a connected app, or a tool the gateway runs for a session reached the platform), `spend` (a session's consumed cost reached `match.amount`, whole US cents; read when a turn ends and at a capability call, once per session), `turn.end` (a turn ended). Actions: `notify` delivers a signed event (`hook.session_start`, `hook.tool_call`, `hook.spend`, `hook.turn_end`) to `webhook_id`, one of the workspace's webhook endpoints, whatever events that endpoint subscribed to; never a URL. `block` at `session.start` refuses the session with 403 `blocked_by_hook_rule`; at `tool.call` it refuses the call with `capability_denied` (`reason: hook_rule`). `require_approval` at `tool.call` asks the session's owner exactly as an `ask` capability policy does, and an answer covers one call. `require_approval` at `session.start` creates the session waiting: it has no sandbox and takes no turn (409 `start_not_approved`), and its task carries an `approval` request for the person who created it, answered `confirm` or `decline` through `POST /tasks/{id}/requests/{request_id}/answer`. Approved, it starts with what it was created with; declined, it is archived, never runs and is charged nothing. A session started in a way that cannot wait (a helper, a product run, a handoff) is refused with 403 `blocked_by_hook_rule`. The most restrictive of the matching rules and the capability policies wins. Refused with 400 and the reason: `block` and `require_approval` at `spend` and at `turn.end`. `match` narrows a rule: `{agent_id}` at `session.start` and `turn.end`, `{capability_id}` or `{connector_app}` (the slug of a connected app), not both, at `tool.call`; omitted, the rule applies to all. A notify rule that cannot be delivered never affects the session. 403 `not_enabled` where hook rules are not turned on; 503 `not_migrated` before the tables exist.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["rules"],"properties":{"rules":{"type":"array","maxItems":20,"items":{"type":"object","required":["point","action"],"properties":{"id":{"type":"string","description":"An existing rule's id, to keep it."},"point":{"type":"string","enum":["session.start","tool.call","spend","turn.end"]},"action":{"type":"string","enum":["notify","block","require_approval"]},"match":{"type":"object","properties":{"agent_id":{"type":"string"},"capability_id":{"type":"string"},"connector_app":{"type":"string","description":"The slug of a connected app, e.g. \"slack\"."},"amount":{"type":"string","description":"Whole US cents, e.g. \"125\" for $1.25. Required at spend."}}},"webhook_id":{"type":"string","description":"Required for notify (whep_…); not allowed otherwise."},"enabled":{"type":"boolean","description":"Default true."}}}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["hook_rules","enabled","can_edit"],"properties":{"enabled":{"type":"boolean","description":"Whether hook rules are turned on for the workspace."},"can_edit":{"type":"boolean","description":"Whether the caller may replace the rules: they are turned on and the caller owns the workspace."},"hook_rules":{"type":"array","items":{"type":"object","required":["id","point","match","action","webhook_id","enabled","created_at","updated_at"],"properties":{"id":{"type":"string","description":"hkr_…"},"point":{"type":"string","enum":["session.start","tool.call","spend","turn.end"]},"match":{"type":"object","additionalProperties":{"type":"string"}},"action":{"type":"string","enum":["notify","block","require_approval"]},"webhook_id":{"type":["string","null"]},"enabled":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/webhooks":{"get":{"summary":"List webhook endpoints [read]","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["webhooks"],"properties":{"webhooks":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Register a webhook endpoint — the whsec_ secret appears only in this response [write]","description":"The URL must be https, with no user name or password, and must not point at a private, loopback or link-local address (400 otherwise). At delivery the host is resolved again: a host that resolves to such an address, and a redirect, are failed attempts.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookEndpoint"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["webhook"],"properties":{"webhook":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/webhooks/{id}":{"get":{"summary":"Webhook endpoint detail [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The webhook endpoint id (whep_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["webhook"],"properties":{"webhook":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Update url/events, or status:active to re-enable a disabled endpoint [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The webhook endpoint id (whep_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchWebhookEndpoint"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["webhook"],"properties":{"webhook":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete a webhook endpoint [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The webhook endpoint id (whep_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/apps":{"get":{"summary":"List BYO channel apps — credentials masked [read]","tags":["channels"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["apps","registered_platforms","shared_platforms"],"properties":{"apps":{"type":"array","items":{"$ref":"#/components/schemas/ChannelApp"}},"registered_platforms":{"type":"array","items":{"type":"string"},"description":"Platforms with a registered-app writer enabled in this service deployment. Does not prove customer credentials or provider delivery."},"shared_platforms":{"type":"array","items":{"type":"string"},"description":"Shared bot choices supported by app selection in this deployment; does not inventory the legacy shared channel flows."}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Register your own bot/number as a channel app [write]","description":"Credentials are proven against the platform where an API exists, stored encrypted, and write-only from then on. The response's setup object carries the steps the platform cannot automate (webhook URLs to paste, invite links).","tags":["channels"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateChannelApp"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelApp"}}}},"202":{"description":"Verification pending","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelApp"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/apps/{id}":{"get":{"summary":"Channel app detail — credentials masked [read]","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The channel app id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelApp"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Rename or rotate credentials (rotation re-runs registration) [write]","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The channel app id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchChannelApp"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelApp"}}}},"202":{"description":"Verification pending","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelApp"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete the channel app [write]","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The channel app id"}],"responses":{"204":{"description":"Deleted"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/connections":{"get":{"summary":"List connections with their bound session [read]","tags":["channels"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["connections"],"properties":{"connections":{"type":"array","items":{"$ref":"#/components/schemas/ChannelConnection"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Connect a surface — link-flow platforms return a pending connect ceremony [write]","description":"telegram/imessage/whatsapp/x/lark/gchat mint a connect ceremony (hosted page or deep link + code) the end user claims in-platform. Slack/Discord with destination.webhook return a LINK ceremony; other Slack/Discord flows create a channel synchronously. Pass app for BYO; callback_url (link flows) redirects the hosted connect page to you after the claim.","tags":["channels"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateChannelConnection"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelConnection"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/connections/status":{"get":{"summary":"Read your connection claim's current status [read]","description":"Look up a link-flow ceremony by its 32-character token, scoped to the authenticated owner and universe. Reconnecting an existing conversation can replace the pending connection ID; this returns the effective ID. It does not confirm downstream webhook processing. Responses are not cached. Normal API rate limits apply; back off on 429.","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","pattern":"^[a-f0-9]{32}$"},"description":"The token after LINK: or in the Telegram start parameter"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["status","connection_id","platform","metadata"],"properties":{"status":{"type":"string","enum":["pending","connected","expired","disconnected"]},"connection_id":{"type":"string"},"platform":{"type":"string"},"metadata":{"type":"object","additionalProperties":true,"description":"The caller's original connection metadata"},"expires_at":{"type":"string","format":"date-time"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/connections/{id}":{"delete":{"summary":"Disconnect the surface [write]","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The connection id"}],"responses":{"204":{"description":"Disconnected"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/connections/{id}/binding":{"put":{"summary":"Set where the surface routes — a session or your webhook endpoint (single active binding) [write]","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The connection id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["destination"],"properties":{"destination":{"type":"object","description":"Exactly one of webhook (endpoint id) or session (session id)","properties":{"webhook":{"type":"string"},"session":{"type":"string"}}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"connection_id":{"type":"string"},"binding_id":{"type":"string"},"session":{"type":"string"},"webhook":{"type":"string"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/connections/{id}/capabilities":{"get":{"summary":"Declared platform capabilities — branch on these instead of guessing [read]","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The connection id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelCapabilities"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/connections/{id}/dev/inbound":{"post":{"summary":"Inject a message into a loopback connection [write]","description":"Local development without a real platform: the message goes through the same webhook pipeline a Telegram or Slack event would. Only loopback connections accept it — anything else answers 400.","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The connection id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelDevInbound"}}}},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"type":"object","required":["thread_id"],"properties":{"thread_id":{"type":"string"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/connections/{id}/dev/outbound":{"get":{"summary":"Everything the agent has sent on a loopback connection [read]","description":"The counterpart to dev/inbound: what a real platform would have received.","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The connection id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["outbound"],"properties":{"outbound":{"type":"array","items":{"type":"object"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/bindings":{"get":{"summary":"List bindings, optionally by connection [read]","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"connection_id","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["bindings"],"properties":{"bindings":{"type":"array","items":{"$ref":"#/components/schemas/ChannelBinding"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Route one thread of a connection to a session or your webhook [write]","tags":["channels"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateChannelBinding"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelBinding"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/bindings/{id}":{"delete":{"summary":"Delete the binding [write]","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The binding id"}],"responses":{"204":{"description":"Deleted"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/identities":{"get":{"summary":"List the chat identities linked to your account [read]","tags":["channels"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["identities"],"properties":{"identities":{"type":"array","items":{"$ref":"#/components/schemas/ChannelIdentity"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Complete a link offered to a person in a connected chat, as the caller [write]","description":"From then on that person's messages in conversations on the same bot or workspace run as the caller's account. The token is the one posted in the chat; it works once and for 30 minutes. 404 when it was used or has expired, 503 `not_migrated` until the platform's tables are in place.","tags":["channels"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}}}}},"responses":{"201":{"description":"Linked","content":{"application/json":{"schema":{"type":"object","required":["identity"],"properties":{"identity":{"$ref":"#/components/schemas/ChannelIdentity"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/identities/links/{token}":{"get":{"summary":"Read who a link would connect, before completing it [read]","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"},"description":"The link token posted in the chat"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["link"],"properties":{"link":{"allOf":[{"$ref":"#/components/schemas/ChannelIdentity"},{"type":"object","properties":{"expires_at":{"type":"string","format":"date-time"}}}]}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/identities/{id}":{"delete":{"summary":"Unlink a chat identity; that person's messages stop running as you [write]","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The identity id"}],"responses":{"204":{"description":"Unlinked"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/webhooks":{"get":{"summary":"List webhook endpoints [read]","tags":["channels"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["webhooks"],"properties":{"webhooks":{"type":"array","items":{"$ref":"#/components/schemas/ChannelWebhookEndpoint"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Create a webhook endpoint — HMAC-signed deliveries, 0/5/30s retries [write]","description":"Deliveries carry X-Asteroids-{Event,Delivery,Timestamp,Signature}; ~20 consecutive failures disable the endpoint. Consumers must be idempotent by delivery id. The message.received payload is described by ChannelMessageReceived, including its optional service-owned claim.","tags":["channels"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateChannelWebhook"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelWebhookEndpoint"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/webhooks/{id}":{"patch":{"summary":"Re-enable a disabled endpoint (resets failures, keeps the secret) and/or re-pick events [write]","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The webhook endpoint id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ACTIVE"]},"events":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelWebhookEndpoint"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete the webhook endpoint [write]","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The webhook endpoint id"}],"responses":{"204":{"description":"Deleted"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/threads/{id}/messages":{"post":{"summary":"Post into a thread — markdown renders natively per platform [write]","description":"File parts use owned Files API assets and require capabilities.files. Long replies are split into complete platform-sized messages. Supply idempotency_key to avoid duplicate sends on retry; an uncertain or partial send must be inspected before choosing a new key. done and failed are mutually exclusive.","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The thread id (from message.received or channel events)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostChannelMessage"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"message_id":{"type":"string"},"thread_id":{"type":"string"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/threads/{id}/messages/{mid}/reactions/{emoji}":{"put":{"summary":"Add a reaction (platform-neutral emoji names) [write]","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The thread id"},{"name":"mid","in":"path","required":true,"schema":{"type":"string"}},{"name":"emoji","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Reacted"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Remove a reaction [write]","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The thread id"},{"name":"mid","in":"path","required":true,"schema":{"type":"string"}},{"name":"emoji","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/deliveries":{"post":{"summary":"Proactive fan-out: post to every thread bound to a destination [write]","tags":["channels"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostChannelDelivery"}}}},"responses":{"200":{"description":"OK — per-thread results","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"thread_id":{"type":"string"},"status":{"type":"string"}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/channels/events/stream":{"get":{"summary":"SSE mirror of your webhook events — for local development [read]","tags":["channels"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"SSE stream","content":{"text/event-stream":{}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/files":{"post":{"summary":"Upload a file — universe-scoped; images are readable back, other uploads are write-once [write]","description":"multipart/form-data with a `file` part and an optional `expires_in_seconds` (3600–7776000). 32 MiB per file (413 file_too_large). Reference the returned id from a message as `{\"type\":\"image\",\"source\":{\"type\":\"file\",\"file_id\":\"file_…\"}}` or a `document` block.","tags":["files"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"},"expires_in_seconds":{"type":"integer","minimum":3600,"maximum":7776000}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/File"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"get":{"summary":"List files — your universe's uploads, or one session's files [read]","description":"Without `scope_id`, the universe's uploads. `scope_id=sess_…` lists that session's files: the copies minted from message content, channel attachments, and agent-stored files. `ids[]` (≤100) returns exactly those files in one page and cannot be combined with page/limit.","tags":["files"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":1000,"default":20}},{"name":"page","in":"query","schema":{"type":"string"},"description":"A next_page cursor"},{"name":"ids[]","in":"query","schema":{"type":"array","items":{"type":"string"}}},{"name":"scope_id","in":"query","schema":{"type":"string"},"description":"sess_…"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileList"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/files/{file_id}":{"get":{"summary":"File metadata [read]","tags":["files"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"file_id","in":"path","required":true,"schema":{"type":"string"},"description":"The file id (file_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/File"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Make an upload always available, or stop [write]","description":"With `attach_by_default: true`, every session created in the workspace from then on starts with a read-only copy at `/workspace/shared/<filename>`, unless the session is created with `defaults: \"none\"`. Only a workspace upload that does not expire can carry the flag (400 otherwise). A file whose name is already taken in a session, or that would take the set past 64 MiB or 50 files, is skipped for that session; the session still starts.","tags":["files"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"file_id","in":"path","required":true,"schema":{"type":"string"},"description":"The file id (file_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["attach_by_default"],"properties":{"attach_by_default":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/File"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete a file [write]","description":"Soft delete: the file stops resolving everywhere; sessions that already received a copy keep it.","tags":["files"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"file_id","in":"path","required":true,"schema":{"type":"string"},"description":"The file id (file_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileDeleted"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/files/{file_id}/content":{"get":{"summary":"Download a file's bytes [read]","description":"Only `downloadable` files (an image upload, readable within the workspace, and every session-scoped file: message copies, channel attachments, agent outputs); other uploads answer 400 not_downloadable. 404 once the file has expired.","tags":["files"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"file_id","in":"path","required":true,"schema":{"type":"string"},"description":"The file id (file_…)"}],"responses":{"200":{"description":"The bytes, with content-type and content-disposition","content":{"*/*":{}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/memory_stores":{"get":{"operationId":"listMemoryStores","summary":"List memory stores [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"include_archived","in":"query","schema":{"type":"boolean"}},{"name":"after","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":100}}],"responses":{"200":{"description":"List of memory stores","content":{"application/json":{"schema":{"type":"object","required":["memory_stores","has_more"],"properties":{"memory_stores":{"type":"array","items":{"$ref":"#/components/schemas/MemoryStore"}},"has_more":{"type":"boolean"},"next_cursor":{"type":"string","description":"Opaque cursor; pass as `after` on the next request."}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"operationId":"createMemoryStore","summary":"Create a memory store [write]","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":255},"description":{"type":"string","maxLength":4096},"attach_by_default":{"type":"string","enum":["none","read_only"]}}}}}},"responses":{"201":{"description":"Created memory store","content":{"application/json":{"schema":{"type":"object","required":["memory_store"],"properties":{"memory_store":{"$ref":"#/components/schemas/MemoryStore"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/memory_stores/{store_id}":{"get":{"operationId":"getMemoryStore","summary":"Get a memory store [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"store_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory store id (memstore_…)"}],"responses":{"200":{"description":"Memory store","content":{"application/json":{"schema":{"type":"object","required":["memory_store"],"properties":{"memory_store":{"$ref":"#/components/schemas/MemoryStore"}}}}}},"404":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"operationId":"updateMemoryStore","summary":"Update a memory store [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"store_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory store id (memstore_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"description":{"type":"string","maxLength":4096},"attach_by_default":{"type":"string","enum":["none","read_only"]}}}}}},"responses":{"200":{"description":"Updated memory store","content":{"application/json":{"schema":{"type":"object","required":["memory_store"],"properties":{"memory_store":{"$ref":"#/components/schemas/MemoryStore"}}}}}},"404":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"operationId":"deleteMemoryStore","summary":"Delete a memory store [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"store_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory store id (memstore_…)"}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/memory_stores/{store_id}/archive":{"post":{"operationId":"archiveMemoryStore","summary":"Archive a memory store (one-way, idempotent) [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"store_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory store id (memstore_…)"}],"responses":{"200":{"description":"Archived memory store","content":{"application/json":{"schema":{"type":"object","required":["memory_store"],"properties":{"memory_store":{"$ref":"#/components/schemas/MemoryStore"}}}}}},"404":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/memory_stores/{store_id}/memories":{"get":{"operationId":"listMemories","summary":"List memories in a store [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"store_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory store id (memstore_…)"},{"name":"path_prefix","in":"query","schema":{"type":"string"},"description":"Must end with / (default: /)"},{"name":"depth","in":"query","schema":{"type":"integer","enum":[0,1]}},{"name":"after","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":100}}],"responses":{"200":{"description":"List of memories","content":{"application/json":{"schema":{"type":"object","required":["memories","has_more"],"properties":{"memories":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/MemoryCompact"},{"type":"object","required":["type","path"],"properties":{"type":{"type":"string","enum":["memory_prefix"]},"path":{"type":"string","description":"Common path prefix ending with /"}}}]}},"has_more":{"type":"boolean"},"next_cursor":{"type":"string","description":"Opaque cursor; pass as `after` on the next request."}}}}}},"404":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"operationId":"createMemory","summary":"Create a memory [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"store_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory store id (memstore_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["path"],"properties":{"path":{"type":"string","description":"Absolute path starting with /"},"content":{"type":"string","maxLength":102400}}}}}},"responses":{"201":{"description":"Created memory","content":{"application/json":{"schema":{"type":"object","required":["memory","version_id"],"properties":{"memory":{"$ref":"#/components/schemas/MemoryFull"},"version_id":{"type":"string"}}}}}},"409":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/memory_stores/{store_id}/memories/{memory_id}":{"get":{"operationId":"getMemory","summary":"Get a memory with content [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"store_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory store id (memstore_…)"},{"name":"memory_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory id (mem_…)"}],"responses":{"200":{"description":"Memory with content","content":{"application/json":{"schema":{"type":"object","required":["memory"],"properties":{"memory":{"$ref":"#/components/schemas/MemoryFull"}}}}}},"404":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"operationId":"updateMemory","summary":"Update a memory [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"store_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory store id (memstore_…)"},{"name":"memory_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory id (mem_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","maxLength":102400},"path":{"type":"string","description":"Rename the memory to this path"},"precondition":{"type":"object","required":["type","content_sha256"],"properties":{"type":{"type":"string","enum":["content_sha256"]},"content_sha256":{"type":"string"}}}}}}}},"responses":{"200":{"description":"Updated memory","content":{"application/json":{"schema":{"type":"object","required":["memory","version_id"],"properties":{"memory":{"$ref":"#/components/schemas/MemoryFull"},"version_id":{"type":"string"}}}}}},"404":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"409":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"operationId":"deleteMemory","summary":"Delete a memory [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"store_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory store id (memstore_…)"},{"name":"memory_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory id (mem_…)"}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/memory_stores/{store_id}/memory_versions":{"get":{"operationId":"listMemoryVersions","summary":"List memory versions for a store [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"store_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory store id (memstore_…)"},{"name":"memory_id","in":"query","schema":{"type":"string"},"description":"Filter to a single memory"},{"name":"after","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":100}}],"responses":{"200":{"description":"List of memory versions","content":{"application/json":{"schema":{"type":"object","required":["memory_versions","has_more"],"properties":{"memory_versions":{"type":"array","items":{"$ref":"#/components/schemas/MemoryVersion"}},"has_more":{"type":"boolean"},"next_cursor":{"type":"string","description":"Opaque cursor; pass as `after` on the next request."}}}}}},"404":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/memory_stores/{store_id}/memory_versions/{version_id}":{"get":{"operationId":"getMemoryVersion","summary":"Get a single memory version [read]","security":[{"bearerAuth":[]}],"parameters":[{"name":"store_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory store id (memstore_…)"},{"name":"version_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory version id (memver_…)"}],"responses":{"200":{"description":"Memory version","content":{"application/json":{"schema":{"type":"object","required":["memory_version"],"properties":{"memory_version":{"$ref":"#/components/schemas/MemoryVersion"}}}}}},"404":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/memory_stores/{store_id}/memory_versions/{version_id}/redact":{"post":{"operationId":"redactMemoryVersion","summary":"Redact the content of a memory version [write]","security":[{"bearerAuth":[]}],"parameters":[{"name":"store_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory store id (memstore_…)"},{"name":"version_id","in":"path","required":true,"schema":{"type":"string"},"description":"The memory version id (memver_…)"}],"responses":{"200":{"description":"Redacted memory version","content":{"application/json":{"schema":{"type":"object","required":["memory_version"],"properties":{"memory_version":{"$ref":"#/components/schemas/MemoryVersion"}}}}}},"404":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"409":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/goal":{"get":{"summary":"The session's standing goal, or null [read]","description":"A goal is an objective the session works toward on its own: after each turn settles, the platform grades the work against the goal's criteria and either takes another turn or stops. At most one goal per session.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["goal"],"properties":{"goal":{"oneOf":[{"$ref":"#/components/schemas/Goal"},{"type":"null"}]}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Set the session's goal, replacing any existing one [write]","description":"Work starts immediately — no separate message is needed, and sending one is not how a goal begins. Criteria are optional: omitted, they are derived from the objective so completion is always judged against an explicit list, which the response returns and PATCH can correct. A criterion given as { text, command } is decided by running the command in the session's workspace (exit 0 = met) instead of by the grader. A person's message always outranks the loop: while a turn is running the goal waits, and takes the turn after it. Grading is a model call billed to the session; with an empty wallet deriving criteria is refused with 402 insufficient_credits. Setting a goal stops the run the goal it replaces had started.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":256},"description":"Dedupes a retry of this mutation. The same key with a different body is refused with 409 idempotency_conflict."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoalInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["goal"],"properties":{"goal":{"$ref":"#/components/schemas/Goal"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Edit the goal in place [write]","description":"A course correction for an active or paused goal, not a restart: the iteration count and spend already consumed carry over. Editing criteria marks them as the caller's. A completed or stopped goal returns 409; POST a new goal to start another outcome.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":256},"description":"Dedupes a retry of this mutation. The same key with a different body is refused with 409 idempotency_conflict."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoalPatch"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["goal"],"properties":{"goal":{"$ref":"#/components/schemas/Goal"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Clear the goal [write]","description":"Stops the loop for good with stop_reason \"cleared\", and interrupts the run the goal itself started if one is going. The record stays readable so the session can still report what it was working on; setting a new goal replaces it.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":256},"description":"Dedupes a retry of this mutation. The same key with a different body is refused with 409 idempotency_conflict."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["goal"],"properties":{"goal":{"$ref":"#/components/schemas/Goal"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/goal/pause":{"post":{"summary":"Stop driving the goal [write]","description":"Stops taking turns and interrupts the run the goal itself started, if one is going. A run a person started is left to finish; POST /sessions/{id}/interrupt stops that. Refused with 409 invalid_state unless the goal is active.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":256},"description":"Dedupes a retry of this mutation. The same key with a different body is refused with 409 idempotency_conflict."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["goal"],"properties":{"goal":{"$ref":"#/components/schemas/Goal"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/goal/resume":{"post":{"summary":"Drive the goal again [write]","description":"Any wall-clock deadline moves out by the time the pause consumed. Refused with 409 invalid_state unless the goal is paused.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":256},"description":"Dedupes a retry of this mutation. The same key with a different body is refused with 409 idempotency_conflict."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["goal"],"properties":{"goal":{"$ref":"#/components/schemas/Goal"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/memory":{"get":{"operationId":"readMemory","summary":"Read your personal cross-session memory [read]","tags":["Memory"],"security":[{"bearerAuth":[]}],"description":"Requires read scope. Only unrestricted owner-facing credentials in the authenticated owner's personal universe are supported; restricted tokens, delegated callers, and team universes return 403.","responses":{"200":{"description":"Saved entries and the opaque version required for the next write.","content":{"application/json":{"schema":{"type":"object","required":["entries","version"],"properties":{"entries":{"type":"array","items":{"type":"object","required":["index","text"],"properties":{"index":{"type":"integer","minimum":0},"text":{"type":"string"}}}},"version":{"type":["string","null"]}}}}}},"401":{"description":"Authentication required"},"403":{"description":"insufficient_scope or personal_memory_only: caller or universe is not eligible"}}},"post":{"operationId":"writeMemory","summary":"Save, edit, remove or clear a personal memory [write]","tags":["Memory"],"security":[{"bearerAuth":[]}],"description":"Requires write scope and unrestricted owner-facing credentials in your personal universe. Read GET /memory first and copy its version exactly into expectedVersion, even when entries is empty. The sample uses null for a store before its first write; replace it with the returned version for an existing document. Stale writes return 409; reload and resolve the change instead of overwriting. Entries are limited to 2048 UTF-8 bytes and the complete recall context to 4000 characters. A state-changing clear advances the version; a no-op on an existing document retains it. Clear preserves allocated indexes.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","oneOf":[{"type":"object","properties":{"op":{"type":"string","const":"save"},"text":{"type":"string","minLength":1,"maxLength":8192},"expectedVersion":{"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}]}},"required":["op","text","expectedVersion"],"additionalProperties":false},{"type":"object","properties":{"op":{"type":"string","const":"update"},"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"text":{"type":"string","minLength":1,"maxLength":8192},"expectedVersion":{"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}]}},"required":["op","index","text","expectedVersion"],"additionalProperties":false},{"type":"object","properties":{"op":{"type":"string","const":"remove"},"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"expectedVersion":{"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}]}},"required":["op","index","expectedVersion"],"additionalProperties":false},{"type":"object","properties":{"op":{"type":"string","const":"clear"},"expectedVersion":{"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}]}},"required":["op","expectedVersion"],"additionalProperties":false}]}}}},"responses":{"200":{"description":"Saved entries and the opaque version required for the next write.","content":{"application/json":{"schema":{"type":"object","required":["entries","version"],"properties":{"entries":{"type":"array","items":{"type":"object","required":["index","text"],"properties":{"index":{"type":"integer","minimum":0},"text":{"type":"string"}}}},"version":{"type":["string","null"]}}}}}},"400":{"description":"invalid_memory: invalid operation or memory limit reached"},"401":{"description":"Authentication required"},"403":{"description":"insufficient_scope or personal_memory_only: caller or universe is not eligible"},"409":{"description":"memory_conflict: reload before writing"}}}},"/credit-campaigns":{"get":{"operationId":"listCreditCampaigns","summary":"List live and recent credit campaigns [admin]","tags":["Credit campaigns"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Campaign result","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"campaigns":{"type":"array","items":{"type":"string"}}},"required":["campaigns"],"additionalProperties":false}}}},"400":{"description":"Invalid request"},"401":{"description":"Authentication required"},"403":{"description":"Admin token scope and administrator allowlist membership required"},"404":{"description":"Unknown campaign"},"503":{"description":"Campaign migrations required"}}},"post":{"operationId":"createCreditCampaign","summary":"Issue a public credit link or personal email invitations [admin]","tags":["Credit campaigns"],"security":[{"bearerAuth":[]}],"description":"Only allowlisted administrators can use these operations. Use one UUID requestId per campaign and reuse the identical body after timeouts. Personal emails are deduplicated and each gets a distinct, email-bound single-use code. Existing verified, unbanned recipients are credited immediately. sendEmail explicitly authorizes product email. Code creation is atomic; delivery/credit failures are per recipient. Retry the same request for retry_needed credit results; never change requestId just to retry. Email status sent means SES accepted, not inbox delivery. Sending/uncertain attempts are not automatically resent; use the returned personal link for manual delivery. Responses contain bearer codes: keep private. A different body with the same requestId returns 409.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"requestId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountUsd":{"type":"number"},"expiresInDays":{"type":"integer","minimum":1,"maximum":365},"note":{"type":"string","minLength":1,"maxLength":200},"audience":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"anyone"},"slots":{"type":"integer","minimum":1,"maximum":1000}},"required":["kind","slots"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"recipients"},"emails":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}}},"required":["kind","emails"],"additionalProperties":false}]},"sendEmail":{"default":false,"type":"boolean"}},"required":["requestId","amountUsd","expiresInDays","note","audience"],"additionalProperties":false}}}},"responses":{"201":{"description":"Campaign result","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"campaignId":{"type":"string"},"recipients":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":["string","null"]},"code":{"type":"string"},"url":{"type":"string"},"claim":{"type":"string"},"emailStatus":{"type":"string"},"notifiedAt":{"type":["string","null"]}},"required":["id","email","code","url","claim","emailStatus","notifiedAt"],"additionalProperties":false}}},"required":["campaignId","recipients"],"additionalProperties":false}}}},"400":{"description":"Invalid request"},"401":{"description":"Authentication required"},"403":{"description":"Admin token scope and administrator allowlist membership required"},"404":{"description":"Unknown campaign"},"409":{"description":"requestId reused with different settings"},"415":{"description":"Content-Type must be application/json"},"503":{"description":"Campaign migrations required"}}}},"/credit-campaigns/{id}":{"get":{"operationId":"getCreditCampaign","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"summary":"Read claim, email and recipient usage results [admin]","tags":["Credit campaigns"],"security":[{"bearerAuth":[]}],"description":"Returns grantedUsd, claimed, activeRecipients, agentUsageUsd and individual link states. Usage is agent/runtime ledger spend since first claim, excludes API gateway and is not attribution to the gifted credit pool.","responses":{"200":{"description":"Campaign result","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"campaignId":{"type":"string"},"note":{"type":"string"},"amountUsd":{"type":"number"},"maxRedemptions":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"claimed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"grantedUsd":{"type":"number"},"activeRecipients":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"agentUsageUsd":{"type":"number"},"usageBasis":{"type":"string"},"links":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":["string","null"]},"state":{"type":"string","enum":["active","disabled","expired","exhausted"]},"claimed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"emailStatus":{"type":"string"},"expiresAt":{"type":"string"},"notifiedAt":{"type":["string","null"]},"url":{"type":["string","null"]}},"required":["id","email","state","claimed","emailStatus","expiresAt","notifiedAt","url"],"additionalProperties":false}}},"required":["campaignId","note","amountUsd","maxRedemptions","claimed","grantedUsd","activeRecipients","agentUsageUsd","usageBasis","links"],"additionalProperties":false}}}},"400":{"description":"Invalid request"},"401":{"description":"Authentication required"},"403":{"description":"Admin token scope and administrator allowlist membership required"},"404":{"description":"Unknown campaign"},"503":{"description":"Campaign migrations required"}}},"delete":{"operationId":"disableCreditCampaign","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"summary":"Disable all unclaimed campaign codes [admin]","tags":["Credit campaigns"],"security":[{"bearerAuth":[]}],"description":"Already granted credit stays in recipients' accounts.","responses":{"200":{"description":"Campaign result","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"disabled":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["disabled"],"additionalProperties":false}}}},"400":{"description":"Invalid request"},"401":{"description":"Authentication required"},"403":{"description":"Admin token scope and administrator allowlist membership required"},"404":{"description":"Unknown campaign"},"503":{"description":"Campaign migrations required"}}}},"/context/search":{"get":{"operationId":"searchPersonalContext","summary":"Search saved memory or personal conversations [read]","tags":["Memory"],"security":[{"bearerAuth":[]}],"description":"Searches one platform-owned source in your personal universe. Restricted and delegated callers are refused. The consumer app separately aggregates imports and artifacts; they are not platform data. Results are literal matches in stable source order, not a global relevance ranking. Follow nextCursor until null and inspect partial/coverage before concluding no match exists. Memory entries have no per-entry timestamps, so their coverage reports that time filtering does not apply.","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":1000}},{"name":"scope","in":"query","required":true,"schema":{"type":"string","enum":["memory","sessions"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","description":"Source continuation returned by this query.","schema":{"type":"string"}},{"name":"since","in":"query","description":"Inclusive lower time bound.","schema":{"type":"string","format":"date-time"}},{"name":"until","in":"query","description":"Exclusive upper time bound; must follow since.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"A bounded source page, with continuation and coverage.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"hits":{"maxItems":100,"type":"array","items":{"type":"object","properties":{"hit":{"type":"object","properties":{"source":{"type":"string","enum":["memory","sessions","imports","artifacts"]},"id":{"type":"string"},"title":{"type":"string"},"snippet":{"type":"string"},"occurredAt":{"type":"string"},"ref":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"memory"},"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"version":{"type":["string","null"]}},"required":["kind","index","version"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"session_message"},"sessionId":{"type":"string","minLength":1,"maxLength":200},"messageId":{"type":"string","minLength":1,"maxLength":200}},"required":["kind","sessionId","messageId"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"import_event"},"traceId":{"type":"string","minLength":1,"maxLength":200},"seq":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["kind","traceId","seq"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"artifact"},"artifactId":{"type":"string","minLength":1,"maxLength":200},"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["kind","artifactId","version"],"additionalProperties":false}]},"citation":{"type":"string"}},"required":["source","id","title","snippet","ref"],"additionalProperties":false},"cursor":{"type":"string","maxLength":4096}},"required":["hit","cursor"],"additionalProperties":false}},"nextCursor":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":["string","null"],"maxLength":4096},"coverage":{"type":"string"},"partial":{"type":"boolean"}},"required":["hits","nextCursor","coverage"],"additionalProperties":false}}}},"400":{"description":"Invalid query, source reference, cursor or text offset"},"401":{"description":"Authentication required"},"403":{"description":"The caller lacks personal-context authority or read scope"}}}},"/context/read":{"get":{"operationId":"readPersonalContext","summary":"Read a saved memory or conversation reference [read]","tags":["Memory"],"security":[{"bearerAuth":[]}],"description":"Rechecks personal ownership and deletion. Accepts memory and session_message references from search. Memory returns the current entry and flags version changes; it does not preserve old versions. Message reads return bounded text and adjacent references for surrounding context. Use nextOffset for a long main message; follow adjacent refs to continue reading. All text together is bounded to 20,000 characters per page.","parameters":[{"name":"ref","in":"query","required":true,"description":"URL-encoded JSON source reference copied from a search hit.","schema":{"type":"string","maxLength":2048},"example":"{\"kind\":\"session_message\",\"sessionId\":\"session-id\",\"messageId\":\"message-id\"}"},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"Current reference, text, nextOffset, truncated, updated, adjacent references and coverage.","content":{"application/json":{"schema":{"type":"object","properties":{"ref":{"type":"object"},"text":{"type":"string"},"nextOffset":{"type":["integer","null"]},"truncated":{"type":"boolean"},"updated":{"type":"boolean"},"coverage":{"type":"string"},"adjacent":{"type":"array","items":{"type":"object","properties":{"ref":{"type":"object"},"text":{"type":"string"},"truncated":{"type":"boolean"}}}}}}}}},"400":{"description":"Invalid query, source reference, cursor or text offset"},"401":{"description":"Authentication required"},"403":{"description":"The caller lacks personal-context authority or read scope"},"404":{"description":"Source unavailable or not owned by this caller"},"409":{"description":"Memory changed while paging; read again from offset zero"}}}},"/sessions/{id}/resources":{"get":{"summary":"List the session's resources, oldest first [read]","description":"`limit` (1–1000) pages the list with an opaque `page` cursor; omitted lists every resource in one answer.","tags":["sessions"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id (sess_…)"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":1000}},{"name":"page","in":"query","schema":{"type":"string"},"description":"A next_page cursor"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResourceList"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Add a file to a running session [write]","description":"Files only — repositories and memory stores can only be attached at session create. The file is copied read-only to `/workspace<mount_path>` before the session's next turn; `mount_path` follows the create rules (rooted under /workspace, no escape, no overlap with another resource). 400 too_many_resources past 500 per session; 400 session_archived on an archived session.","tags":["sessions"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id (sess_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddSessionResource"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResource"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/resources/{rid}":{"get":{"summary":"One resource [read]","tags":["sessions"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id (sess_…)"},{"name":"rid","in":"path","required":true,"schema":{"type":"string"},"description":"The resource id (sesrsc_… or smsr_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResource"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Rotate a repository's token [write]","description":"Only `github_repository` resources accept an update, and the token is the only field: it is re-encrypted and the session's egress policy is recompiled and pushed to its live pod — nothing changes inside the sandbox. A file or memory store answers 400. A token that conflicts with another secret's Authorization header on github.com answers 400 egress_header_conflict.","tags":["sessions"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id (sess_…)"},{"name":"rid","in":"path","required":true,"schema":{"type":"string"},"description":"The resource id (sesrsc_… or smsr_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSessionResource"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResource"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Remove a file from the session [write]","description":"Files only — the resource and its per-session copy are deleted and the pod unlinks the file before the session's next turn. A repository or memory store answers 400: neither can be removed mid-session.","tags":["sessions"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id (sess_…)"},{"name":"rid","in":"path","required":true,"schema":{"type":"string"},"description":"The resource id (sesrsc_… or smsr_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResourceDeleted"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/browser":{"get":{"summary":"Read the session browser and live snapshots [read]","description":"Uses the session's existing universe and token restrictions. Viewing reconnects without restarting execution. Expired browsers are finalized; final screenshots and action history remain readable.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"Authorized browser state, or null when the session has no browser. Provider credentials, interactive viewer links and browser connection URLs are never returned.","content":{"application/json":{"schema":{"type":"object","required":["browser"],"properties":{"browser":{"oneOf":[{"$ref":"#/components/schemas/SessionBrowser"},{"type":"null"}]}}}}}},"default":{"description":"Error — { error: { code, message } }"}}},"post":{"summary":"Prepare an isolated browser for a session [write]","description":"Prepare before sending the task's first turn. Requires an active session, positive credit balance and remaining session budget. An identical repeated request reuses the browser; a different configuration or an ended browser returns 409. The browser has a 15-minute lifetime, fixed viewport and bounded actions. Structured Google Flights verification checks visible route, dates, passengers, cabin and results; tasks without verification remain unverified. Browser usage is billed separately from model and runtime usage.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrowserTask"}}}},"responses":{"201":{"description":"Authorized browser state, or null when the session has no browser. Provider credentials, interactive viewer links and browser connection URLs are never returned.","content":{"application/json":{"schema":{"type":"object","required":["browser"],"properties":{"browser":{"oneOf":[{"$ref":"#/components/schemas/SessionBrowser"},{"type":"null"}]}}}}}},"400":{"description":"Error — { error: { code, message } }"},"402":{"description":"Error — { error: { code, message } }"},"409":{"description":"Error — { error: { code, message } }"},"502":{"description":"Error — { error: { code, message } }"},"503":{"description":"Error — { error: { code, message } }"},"default":{"description":"Error — { error: { code, message } }"}}},"delete":{"summary":"Stop the session browser and release its resources [write]","description":"Fences new browser actions before capturing the final page and releasing the browser. Repeated requests retry unfinished cleanup; a session without a browser returns null. This operation stops browser access; use POST /sessions/{id}/interrupt to also interrupt the agent's turn.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The session id"}],"responses":{"200":{"description":"Authorized browser state, or null when the session has no browser. Provider credentials, interactive viewer links and browser connection URLs are never returned.","content":{"application/json":{"schema":{"type":"object","required":["browser"],"properties":{"browser":{"oneOf":[{"$ref":"#/components/schemas/SessionBrowser"},{"type":"null"}]}}}}}},"default":{"description":"Error — { error: { code, message } }"}}}},"/environments":{"get":{"summary":"List the universe's environments, oldest first [read]","tags":["environments"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentList"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Create an environment [write]","description":"The image build starts immediately; the environment is usable as `environment_id` on POST /sessions as soon as it exists, and a session created against a still-building environment waits for the build. Supplying `extends` (an `env_…` id in the same workspace) composes packages, tools.disabled and networking from the parent at write time and records the lineage. `extends` is immutable after create; chain depth is capped at 16.","tags":["environments"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEnvironment"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["environment"],"properties":{"environment":{"$ref":"#/components/schemas/Environment"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/environments/{id}":{"get":{"summary":"One environment [read]","tags":["environments"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The environment id (env_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["environment"],"properties":{"environment":{"$ref":"#/components/schemas/Environment"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Rename an environment or change its config [write]","description":"Omitted fields are left as they are. A changed `config` rebuilds the image; sessions already running keep the image they started on.","tags":["environments"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The environment id (env_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchEnvironment"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["environment"],"properties":{"environment":{"$ref":"#/components/schemas/Environment"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete an environment [write]","tags":["environments"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The environment id (env_…)"}],"responses":{"204":{"description":"Deleted — no body"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/partner/onboarding":{"get":{"summary":"The onboarding instruction for this account [read]","description":"Markdown by default (the reader is a language model); `?format=json` returns the same state as fields. It describes the step this account is actually on, so an agent can fetch it, make the call it names, and fetch it again until it reports the account is live. This is the entry point for white-label onboarding — there is no form.","tags":["partner"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["markdown","json"]}}],"responses":{"200":{"description":"The instruction","content":{"text/markdown":{"schema":{"type":"string"}},"application/json":{"schema":{"$ref":"#/components/schemas/PartnerState"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/partner":{"get":{"summary":"Where this account stands [read]","tags":["partner"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerState"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/partner/application":{"post":{"summary":"Ask to become a white-label partner [write]","description":"A request, not a switch: a person here reads it and decides, and no call advances it in the meantime. One open application per account.","tags":["partner"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyForPartner"}}}},"responses":{"201":{"description":"Accepted for a decision","content":{"application/json":{"schema":{"type":"object","properties":{"application_id":{"type":"string"},"state":{"type":"string"},"next_action":{"type":"string","nullable":true},"message":{"type":"string"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/partner/key-prefix":{"post":{"summary":"Claim the prefix this partner's API keys carry [admin]","description":"The visible half of every key their customers hold: `acme_…` rather than `ast_…`. Changeable only while no keys exist under it — after that, changing it would strand them.","tags":["partner"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimKeyPrefix"}}}},"responses":{"200":{"description":"Claimed","content":{"application/json":{"schema":{"type":"object","properties":{"partner":{"$ref":"#/components/schemas/Partner"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/partner/domains":{"post":{"summary":"Claim a hostname for one plane [admin]","description":"The response leads with the CNAME a person must add at the partner's own registrar — the one step of onboarding nobody on our side can do. Adding the row is not ownership: nothing routes until domain-control validation issues a certificate.","tags":["partner"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddPartnerHostname"}}}},"responses":{"201":{"description":"Claimed, pending DNS","content":{"application/json":{"schema":{"type":"object","properties":{"dns_record":{"type":"string"},"next_action":{"type":"string"},"partner":{"$ref":"#/components/schemas/Partner"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/partner/brand":{"put":{"summary":"Set the names and copy this partner's customers see [admin]","description":"All fields together. A partial brand is refused rather than half-applied: every field left unset falls back to a platform value carrying our name, which would reach their customer.","tags":["partner"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerBrand"}}}},"responses":{"200":{"description":"Saved","content":{"application/json":{"schema":{"type":"object","properties":{"partner":{"$ref":"#/components/schemas/Partner"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/partner/site":{"get":{"summary":"What this partner has set for its own hostnames [read]","tags":["partner"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"site":{"$ref":"#/components/schemas/PartnerSite"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"put":{"summary":"Set how the product looks, which helpers may be hired, and which agents are this partner's [admin]","description":"Send any of `brand`, `helpers` and `agents`; a part left out is left as it is. `brand` is replaced whole, or cleared with null. A person who signs up on one of this partner's hostnames gets a workspace that counts as the partner's: those hostnames list only the agents named in `agents`, and agents in those workspaces may hire only the helpers `helpers` allows (a refused hire answers 403 `helper_not_allowed`). 422 `refused` says in words what was wrong.","tags":["partner"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerSiteInput"}}}},"responses":{"200":{"description":"Saved","content":{"application/json":{"schema":{"type":"object","properties":{"site":{"$ref":"#/components/schemas/PartnerSite"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/vaults":{"get":{"summary":"List the universe's vaults, oldest first [read]","tags":["vaults"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultList"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Create a vault [write]","description":"Pass its id in `vault_ids` on POST /sessions to grant a session its secrets.","tags":["vaults"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateVault"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["vault"],"properties":{"vault":{"$ref":"#/components/schemas/Vault"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/vaults/{id}":{"get":{"summary":"One vault [read]","tags":["vaults"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The vault id (vlt_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["vault"],"properties":{"vault":{"$ref":"#/components/schemas/Vault"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete a vault and every secret in it [write]","description":"The revocation is pushed to the pods of any sessions the vault was attached to — they lose the credentials without restarting.","tags":["vaults"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The vault id (vlt_…)"}],"responses":{"204":{"description":"Deleted — no body"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/vaults/{id}/secrets":{"get":{"summary":"List a vault's secrets [read]","tags":["vaults"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The vault id (vlt_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultSecretList"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Add a secret to a vault [write]","description":"`auth.type` picks the kind: static_bearer and mcp_oauth authenticate an MCP server at `mcp_server_url`; environment_variable exposes `secret_name` to the pod. The value is encrypted at rest and never returned.","tags":["vaults"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The vault id (vlt_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateVaultSecret"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["secret"],"properties":{"secret":{"$ref":"#/components/schemas/VaultSecret"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/vaults/{id}/secrets/move":{"post":{"summary":"Move the secrets of other vaults into this one [write]","description":"Moves every secret of the `from` vaults of the same workspace into this vault and answers what happened to each, by name; a value is never returned. A secret is copied and confirmed stored before its source copy is touched, and the source copy is removed only when no session that is not archived still uses that vault without this one (`source` says which). A name this vault already holds with another value is a `clash` and is left alone unless it is listed in `replace`. A secret past this vault's limit, or one that could not be applied together with this vault's secrets, is `blocked` with a `reason`. Calling again moves nothing twice: what is already here answers `already`. With `dry_run` nothing is written and the outcomes are what a real call would do.","tags":["vaults"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The vault id (vlt_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoveVaultSecrets"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultSecretMove"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/vaults/{id}/secrets/{secretId}":{"patch":{"summary":"Rotate or re-scope a secret in place [write]","description":"The secret keeps its id and its placeholder, so attached pods need no restart — the recompiled policy is pushed to them. Fields not sent are left as they are; `injection_location` merges per field.","tags":["vaults"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The vault id (vlt_…)"},{"name":"secretId","in":"path","required":true,"schema":{"type":"string"},"description":"The secret id (vsec_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVaultSecret"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["secret"],"properties":{"secret":{"$ref":"#/components/schemas/VaultSecret"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete a secret [write]","tags":["vaults"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The vault id (vlt_…)"},{"name":"secretId","in":"path","required":true,"schema":{"type":"string"},"description":"The secret id (vsec_…)"}],"responses":{"204":{"description":"Deleted — no body"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/vaults/{id}/secrets/{secretId}/validate":{"post":{"summary":"Exercise an mcp_oauth grant and report whether it still works [write]","tags":["vaults"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The vault id (vlt_…)"},{"name":"secretId","in":"path","required":true,"schema":{"type":"string"},"description":"The secret id (vsec_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultSecretValidation"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/sessions/{id}/handoff":{"post":{"summary":"Hand this session's context to another agent [write]","description":"Accepted immediately; the move runs in the background. Poll the `status_url` in the response (also sent as the `Location` header) until `status` is terminal, then talk to `target_session`. `last_message_id` bounds how much history is carried; omitted = all of it. An `Idempotency-Key` header dedupes retries.","tags":["sessions"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The source session id (sess_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestSessionHandoff"}}}},"responses":{"202":{"description":"Accepted — poll status_url","content":{"application/json":{"schema":{"type":"object","required":["handoff"],"properties":{"handoff":{"$ref":"#/components/schemas/SessionHandoff"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/session-handoffs/{id}":{"get":{"summary":"The progress of one handoff [read]","tags":["sessions"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The handoff id (handoff_…), as returned by POST /sessions/{id}/handoff"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["handoff"],"properties":{"handoff":{"$ref":"#/components/schemas/SessionHandoff"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/tasks":{"get":{"summary":"List the workspace's tasks [read]","description":"Most recent activity first. Helper and handoff sessions are counted inside their task and never listed on their own.","tags":["tasks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"attention","in":"query","required":false,"schema":{"type":"string","enum":["needs_you","working","done","idle"],"description":"What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new."},"description":"Return only tasks in this state"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["tasks"],"properties":{"tasks":{"type":"array","items":{"$ref":"#/components/schemas/TaskSummary"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/tasks/{id}":{"get":{"summary":"One task with its sessions, open requests and cost [read]","description":"By default the id must name a task root. With by=session, resolves an accessible helper or handoff session to its containing task; both the member and root must be accessible.","tags":["tasks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The task id: the id of its root session (sess_…)"},{"name":"by","in":"query","required":false,"schema":{"type":"string","enum":["session"]},"description":"Resolve this session to its existing task root."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["task"],"properties":{"task":{"$ref":"#/components/schemas/Task"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/tasks/{id}/seen":{"post":{"summary":"Mark the task seen by the caller [write]","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"session_ids":{"type":"array","minItems":1,"items":{"type":"string","minLength":1,"maxLength":256},"description":"Only these task members are marked seen; omitted marks all current members."}}}}}},"description":"Records that the caller has looked at the task now, so a result that already arrived stops reading as `done` for them. Optional session_ids scopes the read to those task members; other members keep their unread results. Other people's view is unchanged. Answers 503 `not_available` until the platform's task tables are in place.","tags":["tasks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The task id: the id of its root session (sess_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["task"],"properties":{"task":{"$ref":"#/components/schemas/Task"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/tasks/{id}/completion_answer":{"put":{"summary":"Say whether the task did the job [write]","description":"The caller's own answer for a task that has a result. Each person has one answer per task; sending it again replaces the earlier one. It counts toward `stats.completed_yes` or `stats.completed_no` of the catalog listing the task's agent stands for. 409 `no_result` while no session of the task has replied. 404 for a task the caller cannot see. Answers 503 `not_migrated` until the platform's answer table is in place.","tags":["tasks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The task id: the id of its root session (sess_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["did_the_job"],"properties":{"did_the_job":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["task"],"properties":{"task":{"$ref":"#/components/schemas/Task"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/tasks/{id}/requests/{request_id}/answer":{"post":{"summary":"Answer a request the task is waiting on [write]","description":"Sends the caller's answer to the session that asked, as its next turn, in the same form a click in the app produces. Pass `option_id` for one of the request's options, or `text` where the request accepts free text. A `spend` request is applied before anything is sent: confirming remembers the price and, when the task itself was waiting to start, holds the fee and starts it with what it was given (402 `insufficient_credits` when the caller's credit does not cover the fee; the request stays open). Declining such a start closes the request and the task never runs. A `spend` request that asks to raise a member's monthly limit in a workspace is answered by an owner or admin of that workspace with `option_id` `raise` or `decline` (403 `request_not_yours` for anyone else, the member included): raising sets the limit the request offered and sends on what the member's waiting tasks were given. An optional `note` is sent to the agent after the answer, in the same turn, and is not part of the answer: a surface other than the app uses it to say where the answer came from and how to reply there. 404 when the task has no open request with that id, 403 `request_not_yours` when it is addressed to someone else, 400 when the answer is not one the request accepts, 409 `session_busy` while the turn that asked is still running (retry once the session is idle).","tags":["tasks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The task id: the id of its root session (sess_…)"},{"name":"request_id","in":"path","required":true,"schema":{"type":"string"},"description":"The request's `id` from the task's `requests`"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","additionalProperties":false,"required":["option_id"],"properties":{"option_id":{"type":"string"},"note":{"type":"string","maxLength":4000}}},{"type":"object","additionalProperties":false,"required":["text"],"properties":{"text":{"type":"string","maxLength":20000},"note":{"type":"string","maxLength":4000}}}]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["session_id","message_id"],"properties":{"session_id":{"type":"string","description":"The session that asked"},"message_id":{"type":["string","null"],"description":"The answer's message; read the session's events from it to follow the turn. Null when a `spend` request was declined, or confirmed for a task that was given nothing to start with."}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/tasks/{id}/agent-fee/dispute":{"post":{"summary":"Say a paid agent did not complete the task [write]","description":"For the person who hired, within 72 hours of the task's first result. The fee and the seller's earning then wait for a reviewer, who either refunds the fee to the caller's credit or lets the charge stand. Usage is not refunded. 404 when the task has no agent fee of the caller's, 409 `not_disputable` outside the 72 hours or once it has been disputed, 400 when the task holds more than one fee and `session_id` does not name one.","tags":["tasks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The task id: the id of its root session (sess_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["reason"],"properties":{"reason":{"type":"string","minLength":1,"maxLength":1000},"session_id":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["task"],"properties":{"task":{"$ref":"#/components/schemas/Task"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/tasks/{id}/files":{"get":{"summary":"List the files in the task's file space [read]","description":"The folder every session of the task has at `/workspace/task/`: a handoff session and a helper see the same files as the session that wrote them. Current files only, by path. Answers 503 `not_migrated` until the platform's task file tables are in place.","tags":["tasks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The task id: the id of its root session (sess_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["files"],"properties":{"files":{"type":"array","items":{"$ref":"#/components/schemas/TaskFile"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/tasks/{id}/export":{"get":{"summary":"Download the task's files as one archive [read]","description":"A zip archive of the current files in the task's file space, each at its own path. 413 `export_too_large` when they are more than 64 MiB together; download them one at a time then.","tags":["tasks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The task id: the id of its root session (sess_…)"}],"responses":{"200":{"description":"The archive","content":{"application/zip":{"schema":{"type":"string","format":"binary"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/tasks/{id}/files/{path}":{"get":{"summary":"Read one task file, or its history [read]","description":"Returns the file's bytes. With `versions=true` returns instead every recorded write of that path, newest first, including writes to a path that has since been deleted.","tags":["tasks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The task id: the id of its root session (sess_…)"},{"name":"path","in":"path","required":true,"schema":{"type":"string"},"description":"The file's path inside the task's file space, such as report.md or data/rows.csv"},{"name":"versions","in":"query","required":false,"schema":{"type":"string","enum":["true"]}}],"responses":{"200":{"description":"The bytes, or the version list","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}},"application/json":{"schema":{"type":"object","required":["versions"],"properties":{"versions":{"type":"array","items":{"$ref":"#/components/schemas/TaskFileVersion"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"put":{"summary":"Write one task file [write]","description":"The body is the file's bytes (16 MiB at most; 413 `file_too_large`). The write becomes the current file. `base_sha256` names what the caller last saw at the path (empty for nothing); when something else is current the write is still made, both versions are kept, and the response says `conflict: true`. A task holds at most 2000 files and 256 MiB (413 `task_files_full`). Sessions of the task pick the file up at the start of their next turn.","tags":["tasks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The task id: the id of its root session (sess_…)"},{"name":"path","in":"path","required":true,"schema":{"type":"string"},"description":"The file's path inside the task's file space, such as report.md or data/rows.csv"},{"name":"base_sha256","in":"query","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["file","conflict"],"properties":{"file":{"$ref":"#/components/schemas/TaskFile"},"conflict":{"type":"boolean"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Remove one task file [write]","description":"Removes the path from the current files. Its history stays readable with `versions=true`.","tags":["tasks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The task id: the id of its root session (sess_…)"},{"name":"path","in":"path","required":true,"schema":{"type":"string"},"description":"The file's path inside the task's file space, such as report.md or data/rows.csv"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/notification-preferences":{"get":{"summary":"Which task events the caller is emailed and pushed about [read]","description":"A person who has never chosen gets the defaults: for email `needs_you` on and `done` off, for push both on. Every task email also carries a link that turns its kind off without signing in.","tags":["notifications"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["notification_preferences"],"properties":{"notification_preferences":{"$ref":"#/components/schemas/NotificationPreferences"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Change which task events the caller is emailed and pushed about [write]","description":"Send `email`, `push` or both, each with only the kinds to change; the response holds all of them. Answers 503 `not_available` until the platform's notification tables are in place.","tags":["notifications"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"email":{"type":"object","additionalProperties":false,"properties":{"needs_you":{"type":"boolean"},"done":{"type":"boolean"}}},"push":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"needs_you":{"type":"boolean"},"done":{"type":"boolean"}}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["notification_preferences"],"properties":{"notification_preferences":{"$ref":"#/components/schemas/NotificationPreferences"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/push-subscriptions":{"get":{"summary":"The browsers the caller is notified in [read]","description":"A subscribed browser gets a push notification when one of the caller's tasks starts waiting on them or has a result, under the same rules as task emails, for the kinds left on under `push` in `/notification-preferences`. `application_server_key` is the key a browser subscribes with; it is null, and the list empty, where push is not turned on.","tags":["notifications"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["application_server_key","data"],"properties":{"application_server_key":{"type":"string","nullable":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/PushSubscription"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Subscribe a browser to push notifications [write]","description":"Send what the browser's `pushManager.subscribe()` returned. Subscribing the same browser again keeps one subscription. Answers 403 `not_enabled` where push is not turned on, 400 for an endpoint that is not a browser push service's, and 503 `not_migrated` until the platform's push tables are in place.","tags":["notifications"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["endpoint","keys"],"properties":{"endpoint":{"type":"string"},"keys":{"type":"object","additionalProperties":false,"required":["p256dh","auth"],"properties":{"p256dh":{"type":"string"},"auth":{"type":"string"}}}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["subscription"],"properties":{"subscription":{"$ref":"#/components/schemas/PushSubscription"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/push-subscriptions/{id}":{"delete":{"summary":"Stop notifying one of the caller's browsers [write]","tags":["notifications"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/connectors/apps":{"get":{"summary":"List the apps a person can connect [read]","description":"One page of the catalog. With neither `q` nor `cursor` the page leads with the widely used apps. Pages vary in size: continue with `next_cursor` until it is null. Answers 502 `catalog_error` when the catalog cannot be read.","tags":["connectors"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Search by name"},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"A page's `next_cursor`"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["apps","next_cursor"],"properties":{"apps":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorApp"}},"next_cursor":{"type":"string","nullable":true}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/connectors/connections":{"get":{"summary":"List the caller's connections [read]","description":"The accounts the caller connected, by app and then oldest first. Connections belong to the person, not to a workspace. `credit` is what the caller has earned by connecting apps and the most they can earn that way.","tags":["connectors"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["connections","credit"],"properties":{"connections":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorConnection"}},"credit":{"type":"object","required":["earned_usd","cap_usd","granted_apps","eligible_apps"],"properties":{"earned_usd":{"type":"number"},"cap_usd":{"type":"number"},"granted_apps":{"type":"array","items":{"type":"string"},"description":"Slugs of the apps that earned credit."},"eligible_apps":{"type":"array","items":{"type":"string"},"description":"Slugs of the apps whose connection can earn credit."}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Start connecting an app [write]","description":"Answers the address the person's browser opens to sign in to the app and allow access. Afterwards the browser is sent to `success_url`, with `account_id` added to its query, or to `error_url`; the caller then records the result with `POST /connectors/connections/complete`. Both addresses must be https (http is accepted for localhost) and on one origin. Answers 400 `unknown_app` for an app that cannot be connected and 502 `connect_error` when the authorization cannot be started.","tags":["connectors"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["app","success_url","error_url"],"properties":{"app":{"type":"string","description":"The app's slug."},"success_url":{"type":"string"},"error_url":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/connectors/connections/complete":{"post":{"summary":"Record a finished authorization [write]","description":"Call this when the browser arrives at `success_url`. The account is checked against the caller's own accounts at the app's provider, so an account somebody else authorized is refused; without `account_id` the caller's newest account for the app is used. Every task of the caller that was waiting on the app continues. Answers 404 when the caller has no such account and 502 `connect_error` when the provider cannot be read.","tags":["connectors"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["app"],"properties":{"app":{"type":"string"},"account_id":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["connection"],"properties":{"connection":{"type":"object","required":["app","app_name","label","credit_grant"],"properties":{"app":{"type":"string"},"app_name":{"type":"string"},"label":{"type":"string"},"credit_grant":{"type":"object","nullable":true,"description":"Credit given for this connection, when connecting apps earns credit. `status` is granted, already_granted, cap_reached or ineligible.","required":["status"],"properties":{"status":{"type":"string"},"amount_usd":{"type":"number"},"earned_usd":{"type":"number"},"cap_usd":{"type":"number"}}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/connectors/connections/{id}":{"delete":{"summary":"Disconnect one of the caller's connections [write]","description":"Agents stop being able to use the account at once. Answers 404 for a connection that is not the caller's.","tags":["connectors"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Disconnected"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/connectors/github/repos":{"get":{"summary":"List the repositories the caller's GitHub connection can reach [read]","description":"Most recently pushed first, at most 100. Answers 404 `github_not_connected` when the caller has no GitHub connection and 409 `github_reconnect_required` when none of their connections can be used.","tags":["connectors"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["repos"],"properties":{"repos":{"type":"array","items":{"type":"object","required":["full_name","default_branch","private","pushed_at"],"properties":{"full_name":{"type":"string"},"default_branch":{"type":"string"},"private":{"type":"boolean"},"pushed_at":{"type":"string","format":"date-time","nullable":true}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/connectors/links":{"post":{"summary":"Make a link to connect the app a task is waiting on [write]","description":"For a task with an open `connect_app` request (see `GET /tasks/{id}`): a link the person the request is addressed to can open in any browser, without being signed in, to connect the app. Only that person can make it. The link can be used once, within fifteen minutes, and this is the only response that carries it; making another replaces one that was not used. When the app is connected the task continues by itself. Answers 404 when the task has no such open request, 403 `request_not_yours` when it is addressed to somebody else, and 503 `not_migrated` until the platform's link table is in place.","tags":["connectors"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["task_id","request_id"],"properties":{"task_id":{"type":"string","description":"The task (sess_…)"},"request_id":{"type":"string"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["link"],"properties":{"link":{"type":"object","required":["url","expires_at"],"properties":{"url":{"type":"string"},"expires_at":{"type":"string","format":"date-time"}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/connectors/links/{token}":{"get":{"summary":"The page a connect link opens","description":"No Authorization header: the secret in the path is the credential. Answers a page that says what is asked, with a button to continue; looking uses nothing up. A link that is unknown, expired, already used, or whose request is no longer waiting answers the same 404 page. More than 10 requests for one link in a minute answers 429.","tags":["connectors"],"security":[],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"},"description":"The secret part of the link (cnl_…)"}],"responses":{"200":{"description":"The page","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"The link cannot be used","content":{"text/html":{"schema":{"type":"string"}}}},"429":{"description":"Too many requests for this link","content":{"text/html":{"schema":{"type":"string"}}}}}},"post":{"summary":"Continue from a connect link to the app's authorization","description":"What the page's button sends. Uses the link up and redirects the browser to the app's sign-in. Refused exactly as the page is.","tags":["connectors"],"security":[],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"303":{"description":"Redirect to the app's authorization"},"404":{"description":"The link cannot be used","content":{"text/html":{"schema":{"type":"string"}}}},"429":{"description":"Too many requests for this link","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/connectors/links/{token}/done":{"get":{"summary":"Where the app's authorization returns for a connect link","description":"The browser arrives here after the person allows access. The connection is recorded for the person the link was made for, once, and the waiting task continues. Only a link that was used, within the last hour, is accepted; anything else answers the 404 page.","tags":["connectors"],"security":[],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}},{"name":"account_id","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Connected","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"The link cannot be used","content":{"text/html":{"schema":{"type":"string"}}}},"502":{"description":"The app was not connected","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/oauth_clients":{"get":{"summary":"The apps the caller registered [read]","description":"Answers 404 until apps with sign-in are open on the platform.","tags":["oauth_clients"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["oauth_clients"],"properties":{"oauth_clients":{"type":"array","items":{"$ref":"#/components/schemas/OauthClient"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Register an app that signs people in [write]","description":"The app signs a person in with the authorization-code flow and PKCE (S256) at the sign-in service, asking for `openid` plus the scopes registered here and naming this API as the `resource`. The access token it receives is sent as `Authorization: Bearer` to this API. It acts as that person in one workspace: a person who belongs to several chooses it when they allow the app, and the app is refused everywhere else (`universe_mismatch` for another workspace named in `X-Universe`, `not_found` for a session outside it). It holds only the scopes they allowed and reaches tasks, sessions, agents, the catalog and whoami. On a session in that workspace it can also send messages and interrupts (`POST /sessions/{id}/events`, `POST /sessions/{id}/interrupt`, both `write`) and follow the live stream (`GET /sessions/{id}/stream`, `read`). It stops working as soon as the person removes the app from their account page: the next request is refused, and a stream that is open ends within a few seconds. To move the app to another workspace the person removes its access and allows it again. A new app is unreviewed. A caller may register up to 10 apps. Answers 404 until apps with sign-in are open on the platform, and 503 `not_migrated` until its tables are in place.","tags":["oauth_clients"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","redirect_uris","scopes"],"properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"Shown to people when they are asked to allow the app."},"redirect_uris":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"string"},"description":"Where the app may send people back after they decide. Matched exactly: no wildcards, no fragments. Must be https; `http://localhost` and `http://127.0.0.1` are accepted while the app is not reviewed."},"scopes":{"type":"array","minItems":1,"items":{"type":"string","enum":["read","write"]},"description":"What the app may ask a person for. `read` sees their tasks, agents and sessions; `write` also starts and changes them."},"test_users":{"type":"array","maxItems":10,"items":{"type":"string","format":"email"},"description":"People besides you who may use the app before it is reviewed, by the email address of their account."}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["oauth_client","client_secret"],"properties":{"oauth_client":{"$ref":"#/components/schemas/OauthClient"},"client_secret":{"type":"string","description":"Shown in this response only. Keep it on your server."}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/oauth_clients/{id}":{"get":{"summary":"One of the caller's apps [read]","tags":["oauth_clients"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The app's client id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["oauth_client"],"properties":{"oauth_client":{"$ref":"#/components/schemas/OauthClient"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Change one of the caller's apps [write]","description":"Send only the fields to change. Changing the name, the redirect URLs or the scopes of an approved app returns it to unreviewed; changing its test users does not.","tags":["oauth_clients"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The app's client id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"Shown to people when they are asked to allow the app."},"redirect_uris":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"string"},"description":"Where the app may send people back after they decide. Matched exactly: no wildcards, no fragments. Must be https; `http://localhost` and `http://127.0.0.1` are accepted while the app is not reviewed."},"scopes":{"type":"array","minItems":1,"items":{"type":"string","enum":["read","write"]},"description":"What the app may ask a person for. `read` sees their tasks, agents and sessions; `write` also starts and changes them."},"test_users":{"type":"array","maxItems":10,"items":{"type":"string","format":"email"},"description":"People besides you who may use the app before it is reviewed, by the email address of their account."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["oauth_client"],"properties":{"oauth_client":{"$ref":"#/components/schemas/OauthClient"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete one of the caller's apps [write]","description":"Everyone's access through the app ends with it.","tags":["oauth_clients"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The app's client id."}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/oauth_clients/{id}/rotate_secret":{"post":{"summary":"Replace an app's client secret [write]","description":"The previous secret stops working at once. People who already allowed the app keep their access.","tags":["oauth_clients"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The app's client id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["oauth_client","client_secret"],"properties":{"oauth_client":{"$ref":"#/components/schemas/OauthClient"},"client_secret":{"type":"string","description":"Shown in this response only. Keep it on your server."}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/catalog/engines":{"get":{"summary":"Read operational harness availability [public]","description":"The delisted engine identities, read without an HTTP cache. New acquisition rejects them; existing sessions are retained.","security":[],"responses":{"200":{"description":"Current delisting state","content":{"application/json":{"schema":{"type":"object","required":["delisted"],"properties":{"delisted":{"type":"array","items":{"type":"string"}}}}}}}}}},"/catalog/agents":{"get":{"summary":"List hireable agents [public]","description":"Every listed agent: platform engines, and other people's agents that were reviewed and approved, each served as it was approved and carrying `seller`. Needs no credentials; a caller that sends them also gets its own workspace's listings. Answers 503 `not_migrated` until the platform's catalog tables are in place.","tags":["catalog"],"security":[],"parameters":[{"name":"category","in":"query","required":false,"schema":{"type":"string","enum":["websites","content","video","code","research","general"]}},{"name":"q","in":"query","required":false,"schema":{"type":"string"},"description":"Matches handle, name, tagline and description"},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["most_used","best_rated","newest"],"default":"most_used"}},{"name":"requires","in":"query","required":false,"schema":{"type":"string","enum":["account","no_account","mcp_servers"]},"description":"Keep the agents whose stated requirements match: `account` needs the caller's own account at a vendor, `no_account` needs none, `mcp_servers` can use MCP servers. An account requirement is stated only where external accounts are turned on."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["agents"],"properties":{"agents":{"type":"array","items":{"$ref":"#/components/schemas/CatalogAgent"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/catalog/agents/{handle}":{"get":{"summary":"One agent by handle [public]","tags":["catalog"],"security":[],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"},"description":"The agent's handle; a leading @ is accepted"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["agent"],"properties":{"agent":{"$ref":"#/components/schemas/CatalogAgent"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/catalog/listings":{"post":{"summary":"List one of your own agents under a handle [write]","description":"The listing is visible to your workspace only, and `agent: \"@handle\"` then starts a session with that agent. A handle is unique across the platform, engines included; a taken one is 409 `handle_taken`. Listing the same agent again replaces its listing and frees the old handle. A listing whose agent is archived or deleted stops being offered.","tags":["catalog"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["agent_id","handle","tagline"],"properties":{"agent_id":{"type":"string"},"handle":{"type":"string","description":"2 to 40 lower-case letters, digits or underscores; a leading @ is accepted"},"tagline":{"type":"string","maxLength":140},"description":{"type":"string","maxLength":4000},"categories":{"type":"array","items":{"type":"string","enum":["websites","content","video","code","research","general"]},"description":"Defaults to general"},"does":{"type":"array","maxItems":10,"items":{"type":"string","maxLength":300}},"does_not":{"type":"array","maxItems":10,"items":{"type":"string","maxLength":300}},"examples":{"type":"array","maxItems":10,"items":{"type":"string","maxLength":300}}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["agent"],"properties":{"agent":{"$ref":"#/components/schemas/CatalogAgent"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/catalog/listings/{handle}":{"delete":{"summary":"Take one of your own listings down [write]","description":"The agent itself is untouched. 404 for a handle that is not one of this workspace's listings.","tags":["catalog"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"},"description":"The agent's handle; a leading @ is accepted"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/catalog/listings/{handle}/conformance":{"post":{"summary":"Start a conformance run of one of your own listings [write]","description":"Answers at once with the run as `running`; read it back with GET. The suite uses the listing the way a customer would, through this API and as you: it starts sessions in your workspace, which you pay for, and deletes them when it is done. 404 for a handle that is not one of this workspace's listings, an engine included. 409 `conformance_running` while a run of that listing is still going.","tags":["catalog"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"},"description":"The agent's handle; a leading @ is accepted"}],"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"type":"object","required":["run"],"properties":{"run":{"$ref":"#/components/schemas/ConformanceRun"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"get":{"summary":"The latest conformance run of one of your own listings [read]","description":"`run` is null when the listing has never been run. 404 for a handle that is not one of this workspace's listings.","tags":["catalog"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"},"description":"The agent's handle; a leading @ is accepted"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["run"],"properties":{"run":{"oneOf":[{"$ref":"#/components/schemas/ConformanceRun"},{"type":"null"}]}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/catalog/listings/{handle}/submission":{"get":{"summary":"Where one of your own listings stands with the public Market [read]","description":"Whether it can be submitted and what is missing, its latest submission, and the approved version being served. 404 for a handle that is not one of this workspace's listings.","tags":["catalog"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"},"description":"The agent's handle; a leading @ is accepted"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingSubmissionState"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Submit one of your own listings for the public Market [write]","description":"Stores the listing and its agent as they are now and puts them in front of a reviewer. Once approved, everyone sees the listing and can start it with `agent: \"@handle\"`; their session runs a hidden copy of the approved agent in their own workspace, on their own wallet. Later edits are not served until a new submission is approved. `fee` asks a flat fee for each task on top of usage; like everything else it takes effect, and changes, only when a submission carrying it is approved, and a submission without it makes the listing usage-only again. 403 `submissions_closed` when this workspace may not submit. 403 `pricing_closed` when `fee` is sent and this workspace may not set a price. 422 `not_submittable` when something is missing: the message names every item. 409 `already_in_review` while an earlier submission is waiting.","tags":["catalog"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"},"description":"The agent's handle; a leading @ is accepted"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["seller_name"],"properties":{"seller_name":{"type":"string","minLength":2,"maxLength":60,"description":"The name the Market shows as the maker. Not an email address."},"fee":{"type":"object","additionalProperties":false,"required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^[1-9][0-9]*$","description":"Whole US cents"},"currency":{"type":"string","enum":["USD"]}},"description":"The flat fee for each task, in whole US cents: 1 to 100000"}}}}}},"responses":{"201":{"description":"Submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingSubmissionState"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Withdraw a submission that is waiting for review [write]","description":"404 when nothing of this listing is waiting.","tags":["catalog"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"},"description":"The agent's handle; a leading @ is accepted"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingSubmissionState"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/catalog/listings/{handle}/publication":{"delete":{"summary":"Stop serving one of your own listings to everyone else [write]","description":"The workspace listing and the agent stay. Sessions other people already started keep running. 404 when the listing is not public.","tags":["catalog"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"},"description":"The agent's handle; a leading @ is accepted"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingSubmissionState"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/seller/earnings":{"get":{"summary":"What you have earned from the fees on your public listings [read]","description":"Totals, a line per listing, a line per captured fee (newest first) and the payouts they went into. The seller keeps the share shown on each line; the rest is the platform's. A `referral` line is the caller's share of a fee another seller's agent was paid by a person the caller brought; it counts in `earned`, `paid` and `unpaid`, not in `gross` or `listings`. A fee is payable once the 72 hours its buyer has to dispute it have passed, and payouts are made once a month. Nothing here identifies a buyer. 404 where flat fees are not offered.","tags":["catalog"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["totals","listings","lines","payouts"],"properties":{"totals":{"type":"object","required":["gross","earned","paid","unpaid"],"properties":{"gross":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents; negative on a reversal"},"currency":{"type":"string","enum":["USD"]}}},"earned":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents; negative on a reversal"},"currency":{"type":"string","enum":["USD"]}}},"paid":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents; negative on a reversal"},"currency":{"type":"string","enum":["USD"]}}},"unpaid":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents; negative on a reversal"},"currency":{"type":"string","enum":["USD"]}}}}},"listings":{"type":"array","items":{"type":"object","required":["handle","tasks","gross","earned"],"properties":{"handle":{"type":"string"},"tasks":{"type":"integer"},"gross":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents; negative on a reversal"},"currency":{"type":"string","enum":["USD"]}}},"earned":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents; negative on a reversal"},"currency":{"type":"string","enum":["USD"]}}}}}},"lines":{"type":"array","items":{"type":"object","required":["id","handle","kind","source","fee","share_percent","earned","status","payable_at","created_at"],"properties":{"id":{"type":"string"},"handle":{"type":"string"},"kind":{"type":"string","enum":["earning","reversal","referral"],"description":"`reversal`: a fee refunded after it had been paid out, taken off the next payout. `referral`: the caller's share of a fee another seller's agent was paid by a person the caller referred (`POST /seller/referrals`); its `fee` is that fee"},"source":{"type":"string","enum":["shelf","seller_referred","helper","referral"],"description":"Who brought the buyer; `referral` on a referral line"},"fee":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents; negative on a reversal"},"currency":{"type":"string","enum":["USD"]}}},"share_percent":{"type":"number"},"earned":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents; negative on a reversal"},"currency":{"type":"string","enum":["USD"]}}},"status":{"type":"string","enum":["waiting","disputed","refunded","payable","in_payout","paid"]},"payable_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}}},"payouts":{"type":"array","items":{"type":"object","required":["id","period_start","period_end","amount","status","paid_at"],"properties":{"id":{"type":"string"},"period_start":{"type":"string","format":"date-time"},"period_end":{"type":"string","format":"date-time"},"amount":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","description":"Whole US cents; negative on a reversal"},"currency":{"type":"string","enum":["USD"]}}},"status":{"type":"string","enum":["owed","paid"]},"paid_at":{"type":["string","null"],"format":"date-time"}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/seller/account":{"get":{"summary":"Your seller account status [read]","description":"Returns the Stripe Connect account status for the caller. 404 when the caller has no seller account record or the payout tables are not yet migrated.","tags":["catalog"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["account_status","payout_connected"],"properties":{"account_status":{"type":"string","enum":["pending","active","restricted"]},"payout_connected":{"type":"boolean","description":"True when the Stripe Connect account is active and transfers can be sent"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Create your seller account record [write]","description":"Creates or upserts the caller's seller account record. Idempotent — calling it again when a record already exists is a no-op. 404 when the payout tables are not yet migrated.","tags":["catalog"],"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/seller/account/connect":{"post":{"summary":"Start or resume Stripe Connect onboarding [write]","description":"Returns a single-use Stripe account-link URL the seller opens to complete payout setup. 404 when the payout tables are not yet migrated. 503 when the payment processor is not configured.","tags":["catalog"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","description":"Single-use Stripe account-link URL; expires quickly"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/seller/referrals":{"post":{"summary":"Record that a user was referred by you [write]","description":"Records that the target user was brought to the platform by the caller. A user can have at most one referral source; a second call for the same target is a no-op (200, `recorded: false`). 404 when the payout tables are not yet migrated.","tags":["catalog"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["referred_user_id"],"properties":{"referred_user_id":{"type":"string","description":"The id of the user who was referred"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["recorded"],"properties":{"recorded":{"type":"boolean","description":"true when this call created the referral row; false when it already existed"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/seller/notices":{"get":{"summary":"What you were told about the agents you sell [read]","description":"Newest first: a submission approved or sent back, a listing taken down, a lost `Checked` mark, a ruling on a disputed fee, a payout recorded. Each is also mailed once to the seller where task emails are on for the seller's workspace, unless the seller turned these emails off with the link in one of them. `handle` narrows the list to one listing plus the notices that are about none. 404 where neither public submissions nor flat fees are offered.","tags":["catalog"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"handle","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["id","kind","handle","title","text","created_at"],"properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["approved","sent_back","taken_down","checks_failed","dispute_refunded","dispute_upheld","payout_paid"]},"handle":{"type":["string","null"]},"title":{"type":"string"},"text":{"type":"string","description":"The notice in words, with the reviewer's reason or the amount"},"created_at":{"type":"string","format":"date-time"}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/catalog/comparison_counts":{"put":{"summary":"Report comparison counts per handle [first-party]","description":"For the first-party client that records side-by-side comparison verdicts; any other token is refused with 403. The body is a full snapshot taken at `reported_at`: each handle is set to its totals and a handle left out is removed, so sending the same snapshot again changes nothing and an older one never overwrites a newer one. The totals reach `stats.comparisons` and `stats.wins` on the next hourly recount. Answers 503 `not_migrated` until the platform's table is in place.","tags":["catalog"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["reported_at","counts"],"properties":{"reported_at":{"type":"string","format":"date-time"},"counts":{"type":"array","maxItems":1000,"items":{"type":"object","additionalProperties":false,"required":["handle","comparisons","wins"],"properties":{"handle":{"type":"string"},"comparisons":{"type":"integer","minimum":0},"wins":{"type":"integer","minimum":0}}}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["handles"],"properties":{"handles":{"type":"integer"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/catalog/categories":{"get":{"summary":"The category vocabulary [public]","tags":["catalog"],"security":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["categories"],"properties":{"categories":{"type":"array","items":{"type":"object","required":["id","label"],"properties":{"id":{"type":"string","enum":["websites","content","video","code","research","general"]},"label":{"type":"string"}}}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/catalog/environments":{"get":{"summary":"List environment listings on the shelf [public]","description":"All workspace-visible environment listings. Needs no credentials; a caller that sends them may also see their own workspace's unpublished listings. Answers 404 when the shelf is not enabled. Answers 503 `not_migrated` until the shelf migration is applied.","tags":["catalog"],"security":[],"parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string"},"description":"Matches handle, name, tagline and description"},{"name":"category","in":"query","required":false,"schema":{"type":"string","enum":["development","data","ml","security","web","general"]}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["most_used","newest"],"default":"most_used"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["environments"],"properties":{"environments":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentListing"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/catalog/environments/{handle}":{"get":{"summary":"One environment listing by handle [public]","description":"Answers 404 when the shelf is not enabled, the handle is not found, or the listing belongs to a different workspace and the shelf is restricted to this workspace only.","tags":["catalog"],"security":[],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"},"description":"The listing handle"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["environment"],"properties":{"environment":{"$ref":"#/components/schemas/EnvironmentListing"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/catalog/environments/{handle}/install":{"post":{"summary":"Install an environment listing into your workspace [write]","description":"Creates a copy of the listed environment in the caller's workspace that `extends` the original, so composition (packages, tool policy, networking) is applied at write time. A second install of the same listing by the same workspace is idempotent and returns the existing copy. Answers 404 when the shelf is not enabled or the listing is not found. Answers 503 `not_migrated` until the shelf migration is applied.","tags":["catalog"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"},"description":"The listing handle"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["environment"],"properties":{"environment":{"$ref":"#/components/schemas/Environment"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/environments/{id}/listing":{"put":{"summary":"Publish one of your own environments as a listing [write]","description":"Creates or replaces the listing for this environment on the shelf. The environment must belong to the caller's workspace. Answers 404 when the shelf is not enabled for this workspace or the environment is not found. Answers 503 `not_migrated` until the shelf migration is applied.","tags":["environments"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The environment id (env_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["handle","name"],"properties":{"handle":{"type":"string","description":"2 to 40 lower-case letters, digits or underscores; unique across environment listings"},"name":{"type":"string","minLength":1,"maxLength":128},"tagline":{"type":"string","maxLength":140},"description":{"type":"string","maxLength":4000},"categories":{"type":"array","items":{"type":"string","enum":["development","data","ml","security","web","general"]},"description":"Defaults to general"},"visibility":{"type":"string","enum":["workspace"],"description":"Only workspace is supported in this release","default":"workspace"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["listing"],"properties":{"listing":{"$ref":"#/components/schemas/EnvironmentListing"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Remove the listing for one of your own environments [write]","description":"Delists the environment; the environment itself and any installed copies in other workspaces are not touched. Answers 404 when the shelf is not enabled, the environment is not found, or it has no listing. Answers 503 `not_migrated` until the shelf migration is applied.","tags":["environments"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The environment id (env_…)"}],"responses":{"204":{"description":"Delisted"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/catalog/listings/{handle}/hosting":{"get":{"summary":"Where one of the workspace's listings runs [read]","description":"The secret is never returned here. Answers 404 until running an agent on your own server is open for the workspace.","tags":["catalog"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"},"description":"The handle of one of the workspace's own listings."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingHosting"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"put":{"summary":"Run a listing on your own server [write]","description":"Each task given to the listing is then sent to this address instead of a sandbox, as one POST per turn: `{id, type: \"task.turn\", created_at, task: {id, session_id, agent}, message: {id, text}, pass: {token, expires_at}, api_base, callback_url}`. The request is signed like a webhook: `x-asteroids-timestamp`, and `x-asteroids-signature` = `v1=` + HMAC-SHA256 of `<timestamp>.<body>` with the listing's secret; check it before trusting the body. Answer 2xx within 10 seconds, then do the work and report to `callback_url`. The request is made once and is not retried; an address that does not answer 2xx in time ends the turn with an error the person reads. `pass.token` is a Bearer credential for that one turn of that one task. It reads the task (`GET /tasks/{id}`), reports to it (`POST /tasks/{id}/callback`), and reads and writes its files (`/tasks/{id}/files`); every other route refuses it with 403. It stops working when the turn ends, when the person stops the turn or archives the task, or after 15 minutes, whichever is first; a turn still open then is ended with an error. A later message from the person, or their answer to a question, is a new turn with a new pass. The address must be https on the public internet. The first call answers 201 with the signing secret, shown once; a later call changes the address and keeps the secret. A listing that is already public keeps running where its approved version said until a new submission is approved. Answers 404 until running an agent on your own server is open for the workspace. 503 `not_migrated` until its tables are in place.","tags":["catalog"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"},"description":"The handle of one of the workspace's own listings."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["endpoint_url"],"properties":{"endpoint_url":{"type":"string","description":"The https address tasks are sent to."}}}}}},"responses":{"200":{"description":"Address changed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingHosting"}}}},"201":{"description":"Now runs on your server; carries the secret","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingHosting"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Run a listing in a sandbox again [write]","description":"Tasks already started on your server can no longer be sent to it: their next turn ends with an error. Answers 404 until running an agent on your own server is open for the workspace.","tags":["catalog"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"},"description":"The handle of one of the workspace's own listings."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingHosting"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/catalog/listings/{handle}/hosting/secret":{"post":{"summary":"Replace the secret a listing's requests are signed with [write]","description":"Answers the new secret, shown once. The next request is signed with it; the old one is no longer used. Answers 404 until running an agent on your own server is open for the workspace.","tags":["catalog"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"},"description":"The handle of one of the workspace's own listings."}],"responses":{"201":{"description":"Replaced; carries the new secret","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingHosting"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/tasks/{id}/callback":{"post":{"summary":"Report on a task from the server its agent runs on [task pass]","description":"Authorized by the pass handed to that server with the turn, sent as `Authorization: Bearer`, and by nothing else: any other credential is refused with 403. `message` shows progress and keeps the turn open. `result` is the answer; `request` asks the person a question, which they answer like any other request on the task; `error` says the work could not be done. Those three end the turn and the pass, so write the task's files first. 409 `turn_ended` once the turn is over; 401 for a pass that has ended.","tags":["tasks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The task's id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","additionalProperties":false,"required":["type","text"],"properties":{"type":{"const":"message"},"text":{"type":"string","minLength":1,"maxLength":200000}},"description":"Something to show while the work goes on. The turn stays open."},{"type":"object","additionalProperties":false,"required":["type","text"],"properties":{"type":{"const":"result"},"text":{"type":"string","minLength":1,"maxLength":200000}},"description":"The answer. Ends the turn and the pass."},{"type":"object","additionalProperties":false,"required":["type","question"],"description":"A question for the person. Ends the turn and the pass; the answer arrives as the task's next turn, with a new pass.","properties":{"type":{"const":"request"},"question":{"type":"string","minLength":1,"maxLength":2000},"options":{"type":"array","maxItems":10,"items":{"type":"object","additionalProperties":false,"required":["id","label"],"properties":{"id":{"type":"string","maxLength":200},"label":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":500}}}},"allow_free_text":{"type":"boolean","description":"Whether the person may type an answer. Defaults to true; must be true when there are no options."}}},{"type":"object","additionalProperties":false,"required":["type","message"],"properties":{"type":{"const":"error"},"message":{"type":"string","minLength":1,"maxLength":500}},"description":"The work could not be done. Ends the turn and the pass; the person reads the message."}]}}}},"responses":{"200":{"description":"Recorded","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean"},"request_id":{"type":"string","description":"The id of the request that was raised, for `request`."}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/artifacts":{"get":{"summary":"List the workspace's artifacts [read]","description":"Newest first. With `task_id`, that task's only. Answers 503 `not_migrated` until the platform's artifact tables are in place.","tags":["artifacts"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"task_id","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["artifacts"],"properties":{"artifacts":{"type":"array","items":{"$ref":"#/components/schemas/Artifact"}}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Publish task files as an artifact revision [write]","description":"Publishes paths from the task's file space (`/tasks/{id}/files`) as a new revision of the artifact with that name in the task, creating the artifact on first use. A path that names a folder publishes everything under it. The revision records each file's content at this moment; later edits to the task's files do not change it. `entry` defaults to the only file, or to an `index.html`. 400 when a path names nothing; at most 500 files.","tags":["artifacts"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["task_id","name","paths"],"properties":{"task_id":{"type":"string"},"name":{"type":"string","minLength":1,"maxLength":120},"paths":{"type":"array","minItems":1,"maxItems":200,"items":{"type":"string"}},"entry":{"type":"string"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["artifact"],"properties":{"artifact":{"$ref":"#/components/schemas/Artifact"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/artifacts/{id}":{"get":{"summary":"One artifact with every revision [read]","tags":["artifacts"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The artifact id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["artifact"],"properties":{"artifact":{"allOf":[{"$ref":"#/components/schemas/Artifact"},{"type":"object","required":["revisions"],"properties":{"revisions":{"type":"array","items":{"$ref":"#/components/schemas/ArtifactRevision"},"description":"Newest first"}}}]}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Remove an artifact [write]","description":"It stops being listed and its public link stops working. Publishing under the same name in the task afterwards brings it back with the next version number.","tags":["artifacts"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The artifact id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/artifacts/{id}/share":{"post":{"summary":"Turn the artifact's public link on or off [write]","description":"The link needs no credentials and always serves the current revision. Published pages are served sandboxed: their scripts cannot read the platform's cookies or call its API as the visitor. Turning sharing off makes the link stop working; turning it on again gives a new link.","tags":["artifacts"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The artifact id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["enabled"],"properties":{"enabled":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["share_url"],"properties":{"share_url":{"type":["string","null"]}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/artifacts/{id}/export":{"get":{"summary":"Download an artifact as one archive [read]","description":"A zip archive of every file of the current revision, or of `version=N`, each at its published path. 413 `export_too_large` when the files are more than 64 MiB together.","tags":["artifacts"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The artifact id"},{"name":"version","in":"query","required":false,"schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"The archive","content":{"application/zip":{"schema":{"type":"string","format":"binary"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/artifacts/{id}/files/{path}":{"get":{"summary":"Download one file of an artifact [read]","description":"The current revision's file, or `version=N`. Always sent as a download.","tags":["artifacts"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The artifact id"},{"name":"path","in":"path","required":true,"schema":{"type":"string"}},{"name":"version","in":"query","required":false,"schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"The bytes","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/harnesses":{"get":{"summary":"List workspace harnesses, oldest first [read]","description":"Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.","tags":["harnesses"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HarnessList"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Create a harness [write]","description":"Creates a workspace harness with the given handle, name and profile. After creating, add a version with POST /harnesses/{id}/versions, then promote it with POST /harnesses/{id}/versions/{v}/current before creating agents that reference it. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.","tags":["harnesses"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateHarness"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["harness"],"properties":{"harness":{"$ref":"#/components/schemas/Harness"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/harnesses/{id}":{"get":{"summary":"One harness [read]","description":"Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.","tags":["harnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The harness id (hrn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["harness"],"properties":{"harness":{"$ref":"#/components/schemas/Harness"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"summary":"Rename a harness or change its model_billing [write]","description":"Omitted fields are left unchanged. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.","tags":["harnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The harness id (hrn_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchHarness"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["harness"],"properties":{"harness":{"$ref":"#/components/schemas/Harness"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete a harness [write]","description":"Deletes the harness and all its versions. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.","tags":["harnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The harness id (hrn_…)"}],"responses":{"204":{"description":"Deleted — no body"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/harnesses/{id}/versions":{"get":{"summary":"List versions for a harness, oldest first [read]","description":"Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.","tags":["harnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The harness id (hrn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HarnessVersionList"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Register a new harness version [write]","description":"Registers the version string and triggers an E2B template build. Poll the version's status until it reaches ready, then promote with POST /harnesses/{id}/versions/{v}/current. If profile is omitted, the parent harness's profile is used. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.","tags":["harnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The harness id (hrn_…)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateHarnessVersion"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["version"],"properties":{"version":{"$ref":"#/components/schemas/HarnessVersion"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/harnesses/{id}/versions/{v}":{"get":{"summary":"One harness version [read]","description":"Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.","tags":["harnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The harness id (hrn_…)"},{"name":"v","in":"path","required":true,"schema":{"type":"string"},"description":"The harness version string, e.g. v1-4096m"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["version"],"properties":{"version":{"$ref":"#/components/schemas/HarnessVersion"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/harnesses/{id}/versions/{v}/current":{"post":{"summary":"Promote a version to current [write]","description":"Marks this version as the current one for the harness. The previous current version moves back to ready. New agents created against this harness will pin this version. The version must be in ready or current status; a revoked version cannot be promoted. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.","tags":["harnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The harness id (hrn_…)"},{"name":"v","in":"path","required":true,"schema":{"type":"string"},"description":"The harness version string, e.g. v1-4096m"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["version"],"properties":{"version":{"$ref":"#/components/schemas/HarnessVersion"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/harnesses/{id}/versions/{v}/revoke":{"post":{"summary":"Revoke a harness version [write]","description":"Permanently withdraws a version; it cannot be promoted or used for new sessions. Sessions already running on this version continue until they terminate. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.","tags":["harnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The harness id (hrn_…)"},{"name":"v","in":"path","required":true,"schema":{"type":"string"},"description":"The harness version string, e.g. v1-4096m"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["version"],"properties":{"version":{"$ref":"#/components/schemas/HarnessVersion"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/harnesses/{id}/versions/{v}/verify":{"post":{"summary":"Record the E2B template listing for a version [write]","description":"Stores the E2B sandbox listing string for the built template. Called by the build pipeline after a successful build; advances the version status to ready. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.","tags":["harnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The harness id (hrn_…)"},{"name":"v","in":"path","required":true,"schema":{"type":"string"},"description":"The harness version string, e.g. v1-4096m"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyHarnessVersion"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["version"],"properties":{"version":{"$ref":"#/components/schemas/HarnessVersion"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/harnesses/{id}/connect-token":{"post":{"summary":"Mint a connect token for a remote harness (shown once) [write]","description":"Issues a hct_… bearer token the maker's process uses to authenticate to the relay at WS /api/v1/sessions/{id}/harness. Minting revokes any existing token for this harness. The token value is returned exactly once — it cannot be retrieved again. Gated by the REMOTE_HARNESSES platform switch (off → 404). Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.","tags":["harnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The harness id (hrn_…)"}],"responses":{"201":{"description":"Created — one-time token","content":{"application/json":{"schema":{"type":"object","required":["connect_token"],"properties":{"connect_token":{"type":"string","description":"hct_… — store immediately; not retrievable after this response"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Revoke the current connect token for a remote harness [write]","description":"Revokes the active hct_… token. Any maker process currently connected will be dropped on its next frame. Gated by the REMOTE_HARNESSES platform switch. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.","tags":["harnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The harness id (hrn_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/universes/{slug}/pod-provider":{"get":{"summary":"Read the elected BYO provider and whether a credential is registered [admin]","description":"Returns the workspace's elected BYO pod provider name, its optional label, and `has_credential: true`. 404 when BYO_POD_PROVIDER is not enabled for this workspace, no provider is elected, or no credential row exists. 503 `not_migrated` before the credential table exists.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The workspace slug."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"provider":{"type":"string","enum":["e2b","sandbox-oss","daytona"],"description":"The elected provider."},"label":{"type":["string","null"],"description":"The admin-supplied label for this credential."},"has_credential":{"type":"boolean","description":"Always true when the response is present."}}}}}},"default":{"description":"Error — { error: { code, message } }"}}},"put":{"summary":"Register a BYO provider credential for the workspace [admin]","description":"Stores the encrypted provider credential and elects the provider for the workspace. The credential is write-only and never returned by any API. Setting a new credential replaces the old one. 404 when BYO_POD_PROVIDER is not enabled for this workspace. 503 `not_migrated` before the credential table exists.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The workspace slug."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["provider","credential"],"additionalProperties":false,"properties":{"provider":{"type":"string","enum":["e2b","sandbox-oss","daytona"],"description":"The provider to elect."},"credential":{"type":"string","minLength":1,"maxLength":10000,"description":"The provider API key (write-only; never returned)."},"label":{"type":"string","maxLength":128,"description":"Optional human-readable label."}}}}}},"responses":{"200":{"description":"Credential stored and provider elected.","content":{"application/json":{"schema":{"type":"object","properties":{"provider":{"type":"string","enum":["e2b","sandbox-oss","daytona"],"description":"The elected provider."},"label":{"type":["string","null"],"description":"The admin-supplied label for this credential."},"has_credential":{"type":"boolean","description":"Always true when the response is present."}}}}}},"default":{"description":"Error — { error: { code, message } }"}}},"delete":{"summary":"Remove the BYO provider credential and clear the election [admin]","description":"Deletes the credential row and clears Universe.podProvider. Future sessions use the platform's provider. 404 when BYO_POD_PROVIDER is not enabled for this workspace. 503 `not_migrated` before the credential table exists.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The workspace slug."}],"responses":{"200":{"description":"Credential removed.","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean"}}}}}},"default":{"description":"Error — { error: { code, message } }"}}}},"/worker-pools":{"get":{"summary":"List worker pools in the workspace [read]","tags":["worker-pools"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkerPoolList"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"post":{"summary":"Create a worker pool [write]","description":"Returns the pool and a one-time `wpt_…` bearer token the worker machine passes to `GET /worker-pools/{id}/connect`. Store it securely — it is never shown again; call POST /worker-pools/{id}/tokens to rotate.","tags":["worker-pools"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWorkerPool"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkerPoolCreated"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/worker-pools/{id}":{"get":{"summary":"One worker pool [read]","tags":["worker-pools"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The worker pool id (wpool_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkerPool"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"summary":"Delete a worker pool [write]","description":"Disconnects every worker currently connected to the pool.","tags":["worker-pools"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The worker pool id (wpool_…)"}],"responses":{"204":{"description":"Deleted — no body"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/worker-pools/{id}/tokens":{"post":{"summary":"Rotate the pool's connect token [write]","description":"Issues a new `wpt_…` token and immediately invalidates the previous one. Workers currently connected keep their session; they will need the new token on reconnect.","tags":["worker-pools"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The worker pool id (wpool_…)"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkerPoolTokenRotated"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/worker-pools/{id}/workers":{"get":{"summary":"List workers connected to a pool [read]","tags":["worker-pools"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The worker pool id (wpool_…)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkerList"}}}},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/worker-pools/{id}/connect":{"get":{"summary":"Open a worker's control WebSocket [worker]","description":"Workers upgrade this HTTP connection to a WebSocket using `Upgrade: websocket`. Pass the `wpt_…` bearer token in the `Authorization` header. Served by chat-proxy, not asteroids.","tags":["worker-pools"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The worker pool id (wpool_…)"}],"responses":{"101":{"description":"Switching Protocols — WebSocket upgrade accepted"},"401":{"description":"Missing or invalid wpt_… token"},"default":{"description":"Error — { error: { code, message } }","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}}}}