{"openapi":"3.1.0","info":{"title":"Unbrowse API","version":"1.0.0","summary":"Every website's own API, as a tool your agent can call.","description":"Unbrowse turns websites into APIs. Describe a task (\"top stories on hacker news\", \"search eatigo for Italian tonight\") or name a capability, and Unbrowse replays the site's own first-party API over HTTP — signed in as the user when a login is kept in their Unbrowse password manager — instead of driving a browser. Sites nobody has indexed yet are learned in Unbrowse's cloud browser and compiled into a capability on first use.\n\nBilling: verified calls only (failed, refused, challenged and input_required runs are free); $10 per 10,000 calls (500 verified calls a month are free).","contact":{"name":"Unbrowse","email":"hello@unbrowse.ai","url":"https://unbrowse.ai"},"termsOfService":"https://unbrowse.ai/terms"},"externalDocs":{"description":"Docs","url":"https://docs.unbrowse.ai"},"servers":[{"url":"https://alternativeto-net-mcp.unbrowse.ai","description":"Unbrowse"}],"security":[{"oauth2":["unbrowse"]},{"apiKey":[]}],"tags":[{"name":"Runs","description":"Do a task on a website: start, follow, answer what it needs, cancel."},{"name":"Capabilities","description":"Find the tools Unbrowse knows (the user's own and the public index)."},{"name":"Sites","description":"The public index: 8,000+ sites, each with its own tools and OpenAPI spec."},{"name":"Indexing","description":"Teach Unbrowse a site: it explores the site in the cloud browser and compiles tools."},{"name":"Apps & tools","description":"What the workspace enabled, by app; tool scopes with their own MCP URL (/mcp/{slug}); switch tools off; unpublish and republish."},{"name":"Saved queries","description":"A question in plain words, compiled once into an API: typed params, a pinned tool, the same shape every call, and an optional cache."},{"name":"Connected apps","description":"Apps' own MCP servers (Linear, Notion, GitHub…) and Composio toolkits (Gmail, Calendar…) connected with the person's own account; their tools are called through Unbrowse."},{"name":"Marketplace","description":"Every app with its tools, public: search, categories, official MCP servers, agent-readiness."},{"name":"Logins & vault","description":"The password manager: logins go in, only masked hints come out. Sites are signed in to by Unbrowse's browser."},{"name":"Learning","description":"Learn a capability from recorded traffic (HAR or traces); read what was learned."},{"name":"Orgs","description":"For agent builders: an org, its keys, one workspace per end user, and one-time connect links for end users' logins."},{"name":"Replays","description":"Recorded browser sessions: list, read, search and ask across them."},{"name":"Account","description":"Who is signed in and what they have used."},{"name":"Pages","description":"Read any page by URL (scrape): HTML, markdown, text or links, with its real status and timing."}],"paths":{"/api/v1/runs":{"post":{"tags":["Runs"],"operationId":"startRun","summary":"Run a task or a capability","description":"Routes the task to the best capability (or runs the one named), fills its inputs and replays the site's API. Answers with the run: `succeeded` with a verified `result`, `input_required` with `requirements` to answer (POST /api/v1/runs/{runId}/responses), or `failed` with an `error`.\n\nWith `egress: \"client\"` the site requests are sent by you, from your own IP: the answer is `egress_required` with the next request(s) to send (method, URL, headers, body, and a ready `curl`). Send each one and post the raw response to /api/v1/egress/{egressId}; Unbrowse reads it and answers with the next request, or the finished run. Unbrowse decides every request and reads every response; it never contacts the site itself in such a run (no cloud browser, no proxy).","parameters":[{"name":"x-unbrowse-deadline-ms","in":"header","required":false,"schema":{"type":"integer","minimum":5000,"maximum":300000,"default":60000},"description":"Answer within this many ms (clamped to 5,000–300,000; default 60,000). Past it the answer is 504 run_timeout; the run keeps going."},{"name":"deadlineMs","in":"query","required":false,"schema":{"type":"integer","minimum":5000,"maximum":300000,"default":60000},"description":"Same as the x-unbrowse-deadline-ms header (the header wins)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunRequest"}}}},"responses":{"200":{"description":"The run","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"202":{"description":"The run needs input (`input_required`), or, with egress client, the next site request to send (`egress_required`)","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Run"},{"$ref":"#/components/schemas/EgressStep"}]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"504":{"description":"run_timeout: the run did not finish within its deadline. It keeps running: poll `GET /api/v1/runs/{runId}` with the runId given. A verified success is billed once when it lands; a failure is never billed. A retry with the same Idempotency-Key joins the same run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunTimeout"}}}}}}},"/api/v1/scrape":{"post":{"tags":["Pages"],"operationId":"scrape","summary":"Read one page (scrape)","description":"One page by URL, for drop-in migration from hosted scrape APIs. The same path as the `unbrowse.scrape` MCP tool: plain HTTP when the server's HTML carries the content, else Unbrowse's cloud browser renders it. Charged as one verified call only on success. It never runs past `deadlineMs` (default 45 s, clamped 5–120 s). Every answer carries `metadata.statusCode` / `metadata.status` (the page's real HTTP status, also when rendered), `timing` (ms, httpMs, renderMs, queuedMs) and `attempts` (HTTP tries); every error carries the same in `error.details`, with `stage` (http or render), `reason`, `httpStatus` and `renderStatus`.\n\nErrors: 400 invalid input; 402 out of calls; 429 `blocked` (a bot check or an empty page over HTTP and in the browser) with a `Retry-After` header when the page is remembered as walled — for 10 minutes the same host, country and path answer 429 at once; 504 `scrape_timeout` when the deadline passed.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","description":"The page, e.g. https://example.com/pricing (https:// is assumed when missing)."},"country":{"type":"string","description":"Exit country: a two-letter ISO code (US, GB, DE…) or GLOBAL."},"formats":{"type":"array","items":{"type":"string","enum":["markdown","html","text","links","raw"]},"description":"What to return (default [\"html\"]). raw: the body as sent, over HTTP only."},"format":{"type":"string","enum":["raw_html"],"description":"Convenience: the whole page's HTML (formats [\"html\"] with onlyMainContent false)."},"onlyMainContent":{"type":"boolean","description":"Drop navigation, headers, footers and asides (default true)."},"render":{"type":"string","enum":["auto","always","never"],"description":"auto (default): HTTP first, the browser only when the page needs it."},"deadlineMs":{"type":"number","minimum":5000,"maximum":120000,"description":"Overall time budget in ms (default 45000)."}}}}}},"responses":{"200":{"description":"The page","content":{"application/json":{"schema":{"type":"object","properties":{"html":{"type":"string"},"markdown":{"type":"string"},"text":{"type":"string"},"links":{"type":"array","items":{"type":"string"}},"raw":{"type":"string"},"via":{"type":"string","enum":["http","rendered"]},"metadata":{"type":"object","properties":{"statusCode":{"type":"integer"},"status":{"type":"integer"},"url":{"type":"string"},"finalUrl":{"type":"string"},"title":{"type":"string"}},"additionalProperties":true},"timing":{"type":"object","properties":{"ms":{"type":"number"},"httpMs":{"type":"number"},"renderMs":{"type":"number"},"queuedMs":{"type":"number"}}},"attempts":{"type":"integer","description":"HTTP tries (fresh IPs)."}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"504":{"$ref":"#/components/responses/Error"}}}},"/api/v1/runs/{runId}":{"get":{"tags":["Runs"],"operationId":"getRun","summary":"Inspect a run","parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string"},"description":"The run id returned when the run started (run_…), or the one a run_timeout answer names (prun_…)."},{"name":"select","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true,"description":"Keep only these parts of the result (as RunRequest.select)."}],"responses":{"200":{"description":"The run","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/runs/{runId}/events":{"get":{"tags":["Runs"],"operationId":"getRunEvents","summary":"A run's event log","parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string"},"description":"The run id returned when the run started (run_…), or the one a run_timeout answer names (prun_…)."}],"responses":{"200":{"description":"Events","content":{"application/json":{"schema":{"type":"object","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/Object"}}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/runs/{runId}/responses":{"post":{"tags":["Runs"],"operationId":"answerRun","summary":"Answer what a run needs","description":"Supplies the missing inputs, choices or approvals a run asked for (status `input_required`), then continues it.","parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string"},"description":"The run id returned when the run started (run_…), or the one a run_timeout answer names (prun_…)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["expected_state_revision","responses"],"properties":{"expected_state_revision":{"type":"integer","description":"The run's stateRevision when you read its requirements."},"idempotency_key":{"type":"string"},"responses":{"type":"array","items":{"type":"object","required":["requirement_id","expected_revision","action"],"properties":{"requirement_id":{"type":"string"},"expected_revision":{"type":"integer"},"action":{"type":"string","enum":["accept","decline","clear"]},"values":{"type":"object","additionalProperties":true}}}}}}}}},"responses":{"200":{"description":"The run","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/runs/{runId}/cancel":{"post":{"tags":["Runs"],"operationId":"cancelRun","summary":"Cancel a run","parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string"},"description":"The run id returned when the run started (run_…), or the one a run_timeout answer names (prun_…)."}],"responses":{"200":{"description":"The run","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/browse-local":{"post":{"tags":["Runs"],"operationId":"startLocalBrowse","summary":"Start a browser session that runs on the user's own machine","description":"The agent drives the browser (open/snapshot/act/finish), but it runs locally through the CLI's `unbrowse browse --local` — the user's own browser, session and IP. What it learns is kept private to the workspace and is never shared to the public registry (the user's machine is not a trusted recorder). This is a CLI capability; a hosted MCP client cannot reach a local browser.","responses":{"201":{"description":"The session; connect the CLI to drive it","content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string"},"connect":{"type":"string"},"ops":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/browse-local/{sessionId}/op":{"post":{"tags":["Runs"],"operationId":"localBrowseOp","summary":"Issue one browse op (agent side)","description":"open / snapshot / act / finish. Blocks until the connected CLI runs it in the local browser and returns the result; finish returns the learned (private) tool.","parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["op"],"properties":{"op":{"type":"string","enum":["open","snapshot","act","finish"]},"url":{"type":"string"},"ref":{"type":"string"},"action":{"type":"string"},"value":{"type":"string"},"title":{"type":"string"}}}}}},"responses":{"200":{"description":"The op result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/browse-local/{sessionId}/next":{"get":{"tags":["Runs"],"operationId":"localBrowseNext","summary":"CLI: the next op to run (long-poll)","parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The next op, or { idle: true }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/browse-local/{sessionId}/result":{"post":{"tags":["Runs"],"operationId":"localBrowseResult","summary":"CLI: the result of the op it ran","parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["opId","result"],"properties":{"opId":{"type":"string"},"result":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/browse-local/{sessionId}":{"delete":{"tags":["Runs"],"operationId":"closeLocalBrowse","summary":"Close a local-browse session","parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Closed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/egress/{egressId}":{"parameters":[{"name":"egressId","in":"path","required":true,"schema":{"type":"string","pattern":"^eg_[A-Za-z0-9_-]+$"},"description":"From an `egress_required` answer."}],"get":{"tags":["Runs"],"operationId":"getEgress","summary":"What a client-egress run is waiting for","responses":{"200":{"description":"The finished run","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"202":{"description":"The next site request(s)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressStep"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"tags":["Runs"],"operationId":"answerEgress","summary":"Post the site's response to a request you sent","description":"Send the raw response exactly as the site gave it (status, headers, body). If the request could not be sent at all (DNS, TLS, connection refused), send `error` instead; the run treats it as a network error. You have 120 s per request.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["requestId"],"properties":{"requestId":{"type":"string"},"response":{"$ref":"#/components/schemas/EgressResponse"},"error":{"type":"string","description":"Why the request could not be sent."}}}}}},"responses":{"200":{"description":"The finished run","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"202":{"description":"The next site request(s)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressStep"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"delete":{"tags":["Runs"],"operationId":"closeEgress","summary":"Abandon a client-egress run","responses":{"200":{"description":"Closed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/capabilities/search":{"post":{"tags":["Capabilities"],"operationId":"searchCapabilities","summary":"Find capabilities for a task","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"query":{"type":"string","description":"A short task that names the site, e.g. \"hacker news top stories\"."}}}}}},"responses":{"200":{"description":"Matching capabilities","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/capabilities/{capabilityId}":{"get":{"tags":["Capabilities"],"operationId":"getCapability","summary":"One capability: inputs, outputs, how it runs","parameters":[{"name":"capabilityId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The capability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/sites":{"get":{"tags":["Sites"],"operationId":"listSites","summary":"The public index","security":[],"responses":{"200":{"description":"Indexed sites, each with its MCP endpoint and OpenAPI spec","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/sites/{host}":{"get":{"tags":["Sites"],"operationId":"getSite","summary":"A site's tools (public)","security":[],"parameters":[{"name":"host","in":"path","required":true,"schema":{"type":"string"},"description":"The site, e.g. news.ycombinator.com."}],"responses":{"200":{"description":"The site with its tools","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/sites/{host}/readiness":{"get":{"tags":["Sites"],"operationId":"getSiteReadiness","summary":"How ready a site is for agents: what it publishes and a score (public)","security":[],"parameters":[{"name":"host","in":"path","required":true,"schema":{"type":"string"},"description":"The site, e.g. news.ycombinator.com."},{"name":"refresh","in":"query","required":false,"schema":{"type":"string","enum":["1"]},"description":"Check the site again now (at most every 10 minutes)."}],"responses":{"200":{"description":"Score, checks and the fix for each gap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/sites/{host}/official":{"get":{"tags":["Sites"],"operationId":"getSiteOfficialMcp","summary":"The app's own official MCP server, if it runs one (public)","security":[],"parameters":[{"name":"host","in":"path","required":true,"schema":{"type":"string"},"description":"The site, e.g. news.ycombinator.com."}],"responses":{"200":{"description":"Name, endpoint, how it signs in, known tools","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/sites/{host}/mcp":{"post":{"tags":["Sites"],"operationId":"siteMcp","summary":"The site as its own MCP server (Streamable HTTP, JSON-RPC)","parameters":[{"name":"host","in":"path","required":true,"schema":{"type":"string"},"description":"The site, e.g. news.ycombinator.com."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"responses":{"200":{"description":"A JSON-RPC answer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/sites/{host}/skill.md":{"get":{"tags":["Sites"],"operationId":"getSiteSkill","summary":"The site as an Agent Skill (SKILL.md, public)","security":[],"parameters":[{"name":"host","in":"path","required":true,"schema":{"type":"string"},"description":"The site, e.g. news.ycombinator.com."}],"responses":{"200":{"description":"Markdown","content":{"text/markdown":{"schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/marketplace":{"get":{"tags":["Marketplace"],"operationId":"listMarketplace","summary":"Every app with its tools: search, filter, sort (public)","security":[],"parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string"}},{"name":"category","in":"query","required":false,"schema":{"type":"string"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["top","recent","az"]}},{"name":"source","in":"query","required":false,"schema":{"type":"string","enum":["official","unbrowse"]},"description":"official: apps running their own MCP server; unbrowse: apps with tools Unbrowse compiled."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"One page of apps, with totals and category counts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/queries":{"get":{"tags":["Saved queries"],"operationId":"listQueries","summary":"Your saved queries","responses":{"200":{"description":"{ queries: [...] }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"tags":["Saved queries"],"operationId":"compileQuery","summary":"Compile a question into an API","description":"Runs the question once with the example values (a real, verified run), pins the tool it used and learns which of the tool's inputs each {placeholder} fills. The answer names the query's URL: call it with GET /api/v1/q/{queryId}?param=… from then on. When a value is transformed on the way (a city to its code), say where it goes with `map`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"query":{"type":"string","examples":["search hn for {topic}","search eatigo for {cuisine} in {city}"]},"example":{"type":"object","additionalProperties":{"type":"string"},"description":"A value for each {placeholder}, used for the compiling run."},"map":{"type":"object","additionalProperties":{"type":"string"},"description":"Input name → \"{param}\" or a fixed value, where the example values alone are not enough."},"name":{"type":"string"},"maxAge":{"type":"integer","minimum":0,"maximum":604800,"description":"Seconds an answer may be reused (0, the default: never). A reused answer is not billed."}}}}}},"responses":{"201":{"description":"The saved query, with its url and an example call","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/queries/{queryId}":{"get":{"tags":["Saved queries"],"operationId":"getQuery","summary":"One saved query","parameters":[{"name":"queryId","in":"path","required":true,"schema":{"type":"string","pattern":"^q_[A-Za-z0-9_-]{6,40}$"}}],"responses":{"200":{"description":"The saved query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"delete":{"tags":["Saved queries"],"operationId":"deleteQuery","summary":"Delete a saved query","parameters":[{"name":"queryId","in":"path","required":true,"schema":{"type":"string","pattern":"^q_[A-Za-z0-9_-]{6,40}$"}}],"responses":{"200":{"description":"{ removed }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/queries/{queryId}/settings":{"post":{"tags":["Saved queries"],"operationId":"querySettings","summary":"Rename it, or turn its cache on or off","parameters":[{"name":"queryId","in":"path","required":true,"schema":{"type":"string","pattern":"^q_[A-Za-z0-9_-]{6,40}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"maxAge":{"type":"integer","minimum":0,"maximum":604800}}}}}},"responses":{"200":{"description":"The saved query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/queries/{queryId}/recompile":{"post":{"tags":["Saved queries"],"operationId":"recompileQuery","summary":"Recompile: accept a new answer shape or a new tool (same id)","parameters":[{"name":"queryId","in":"path","required":true,"schema":{"type":"string","pattern":"^q_[A-Za-z0-9_-]{6,40}$"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"example":{"type":"object","additionalProperties":{"type":"string"}}}}}}},"responses":{"200":{"description":"The saved query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/q/{queryId}":{"get":{"tags":["Saved queries"],"operationId":"callQuery","summary":"Call a saved query: its params as the query string","description":"Answers { status, result, verified, cached, age?, runId }. 409 `schema_changed` when the answer lost fields it had when compiled, 409 `stale` when its tool is gone: recompile. `fresh=1` skips the cache.","parameters":[{"name":"queryId","in":"path","required":true,"schema":{"type":"string","pattern":"^q_[A-Za-z0-9_-]{6,40}$"}},{"name":"fresh","in":"query","required":false,"schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"The answer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"202":{"description":"The run needs input (input_required)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"tags":["Saved queries"],"operationId":"callQueryPost","summary":"Call a saved query: its params as a JSON body","parameters":[{"name":"queryId","in":"path","required":true,"schema":{"type":"string","pattern":"^q_[A-Za-z0-9_-]{6,40}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"The answer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"202":{"description":"The run needs input (input_required)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/connectors":{"get":{"tags":["Connected apps"],"operationId":"listConnections","summary":"The workspace's connected apps (never a token)","responses":{"200":{"description":"{ connected: [...] }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/connectors/apps":{"get":{"tags":["Connected apps"],"operationId":"searchConnectableApps","summary":"Apps that can be connected (public)","security":[],"parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"{ total, apps: [{ id, name, how: open | sign_in | key }] }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/connectors/connect":{"post":{"tags":["Connected apps"],"operationId":"connectApp","summary":"Connect an app with the person's own account","description":"Open servers connect at once (`connected`). Sign-in apps answer `sign_in` with the app's own OAuth link: send the person there; they land on `returnTo` afterwards. Key apps answer `key` until a `key` is sent (never paste a key into a chat).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["app"],"properties":{"app":{"type":"string","examples":["linear.app","gmail"]},"returnTo":{"type":"string","description":"A path on this site to land on after signing in."},"key":{"type":"string"},"header":{"type":"string","default":"authorization"}}}}}},"responses":{"200":{"description":"{ status: connected | sign_in | key, app, url?, tools? }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/connectors/disconnect":{"post":{"tags":["Connected apps"],"operationId":"disconnectApp","summary":"Disconnect an app (and revoke its token at the app)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["app"],"properties":{"app":{"type":"string"}}}}}},"responses":{"200":{"description":"{ app, removed, revoked }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/connectors/tools":{"get":{"tags":["Connected apps"],"operationId":"listConnectedTools","summary":"The connected apps' tools, as MCP tool definitions (<app>__<tool>)","responses":{"200":{"description":"{ tools: [...] }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/connectors/call":{"post":{"tags":["Connected apps"],"operationId":"callConnectedTool","summary":"Call a connected app's tool","description":"When the app needs the person to sign in again, the answer is 401 with `signIn.url`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tool"],"properties":{"tool":{"type":"string","examples":["linear_app__list_issues"]},"arguments":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"{ isError, content, structured? }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/logins":{"get":{"tags":["Logins & vault"],"operationId":"listLogins","summary":"Saved logins, as masked hints","description":"One page (default 50) with the total count. Pass `origin` for the site you need; follow `nextCursor` for more.","parameters":[{"name":"origin","in":"query","required":false,"schema":{"type":"string"},"description":"Only logins usable on this site, e.g. https://github.com."},{"name":"query","in":"query","required":false,"schema":{"type":"string"},"description":"Only logins whose site, label or masked username/email contains this text."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"The previous page's nextCursor."}],"responses":{"200":{"description":"{ logins: [...], total, nextCursor? }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"tags":["Logins & vault"],"operationId":"saveLogin","summary":"Save (or update) a site's login","description":"One login per site: saving again for the same origin updates it. Only masked hints come back.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["origin"],"properties":{"origin":{"type":"string","format":"uri","examples":["https://app.example.com"]},"username":{"type":"string"},"email":{"type":"string"},"password":{"type":"string"},"totp":{"type":"string","description":"The site's 2FA seed (base32)."},"label":{"type":"string"}}}}}},"responses":{"200":{"description":"The login, masked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/logins/remove":{"post":{"tags":["Logins & vault"],"operationId":"removeLogin","summary":"Forget a login (and its kept session)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"origin":{"type":"string","format":"uri"},"ref":{"type":"string"}}}}}},"responses":{"200":{"description":"{ removed }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/vault":{"get":{"tags":["Logins & vault"],"operationId":"getVault","summary":"Vault references and audit (never secrets)","responses":{"200":{"description":"Refs and audit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/accounts/connections":{"post":{"tags":["Logins & vault"],"operationId":"connectAccount","summary":"Vault an existing account for a site","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["origin"],"properties":{"origin":{"type":"string","format":"uri"},"username":{"type":"string"},"password":{"type":"string"},"label":{"type":"string"}}}}}},"responses":{"200":{"description":"A vault:// reference","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/accounts/register":{"post":{"tags":["Logins & vault"],"operationId":"registerAccount","summary":"Generate and vault a new account's password","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["origin","username"],"properties":{"origin":{"type":"string","format":"uri"},"username":{"type":"string"},"label":{"type":"string"}}}}}},"responses":{"200":{"description":"A vault:// reference","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/learn":{"post":{"tags":["Learning"],"operationId":"learn","summary":"Learn a capability from recorded traffic","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"har":{"$ref":"#/components/schemas/Object"},"traces":{"type":"array","items":{"$ref":"#/components/schemas/Object"}},"goal":{"type":"string"},"title":{"type":"string"}}}}}},"responses":{"201":{"description":"The learned capability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/learned/{id}":{"get":{"tags":["Learning"],"operationId":"getLearned","summary":"One learned capability","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The capability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/learned/{id}/harness.yaml":{"get":{"tags":["Learning"],"operationId":"getLearnedHarness","summary":"A learned capability as harness YAML","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"YAML","content":{"text/yaml":{"schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/learned/{id}/skill.md":{"get":{"tags":["Learning"],"operationId":"getLearnedSkill","summary":"A learned capability as an Agent Skill","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Markdown","content":{"text/markdown":{"schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/skills":{"get":{"tags":["Learning"],"operationId":"listSkills","summary":"The workspace's skills","responses":{"200":{"description":"{ skills: [...] }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/org":{"get":{"tags":["Orgs"],"operationId":"getOrg","summary":"The org: members, end users with usage, tools, keys, credits","responses":{"200":{"description":"The org","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"tags":["Orgs"],"operationId":"createOrg","summary":"Create an org (you become the owner)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"appName":{"type":"string"},"domain":{"type":"string"}}}}}},"responses":{"200":{"description":"The org","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/org/keys":{"post":{"tags":["Orgs"],"operationId":"mintOrgKey","summary":"Mint an org key (shown once)","description":"An org key acts for its end users with the header `X-Unbrowse-End-User: <your user's id>`: each gets their own workspace, logins and usage.","responses":{"200":{"description":"{ token }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/org/keys/revoke":{"post":{"tags":["Orgs"],"operationId":"revokeOrgKey","summary":"Revoke an org or end-user key","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["id"],"properties":{"id":{"type":"string"}}}}}},"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/org/users":{"post":{"tags":["Orgs"],"operationId":"mintEndUserKey","summary":"A key for one end user (for MCP clients that cannot send headers)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["user"],"properties":{"user":{"type":"string"}}}}}},"responses":{"200":{"description":"{ token }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/org/settings":{"post":{"tags":["Orgs"],"operationId":"setOrgSettings","summary":"Share the org's tools on to the public registry","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sharePublic":{"type":"boolean"}}}}}},"responses":{"200":{"description":"The org","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/connect/{requestId}":{"get":{"tags":["Orgs"],"operationId":"getConnectLink","summary":"A one-time connect link: what is asked, by which app (no sign-in)","security":[],"parameters":[{"name":"requestId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"App, site, fields, status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"tags":["Orgs"],"operationId":"fulfilConnectLink","summary":"Save the login the link asks for, in that end user's workspace (works once)","security":[],"parameters":[{"name":"requestId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"username":{"type":"string"},"email":{"type":"string"},"password":{"type":"string"},"totp":{"type":"string"}}}}}},"responses":{"200":{"description":"The link's new status (never the login)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/replays":{"get":{"tags":["Replays"],"operationId":"listReplays","summary":"Recorded sessions","parameters":[{"name":"source","in":"query","required":false,"schema":{"type":"string"}},{"name":"site","in":"query","required":false,"schema":{"type":"string"}},{"name":"outcome","in":"query","required":false,"schema":{"type":"string"}},{"name":"hasError","in":"query","required":false,"schema":{"type":"string"}},{"name":"from","in":"query","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sessions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/replays/{sid}":{"get":{"tags":["Replays"],"operationId":"getReplay","summary":"One session: details, signals, summary","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"delete":{"tags":["Replays"],"operationId":"deleteReplay","summary":"Erase a session","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Erased","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/replays/{sid}/timeline":{"get":{"tags":["Replays"],"operationId":"getReplayTimeline","summary":"The session as text lines","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["text"]}}],"responses":{"200":{"description":"Timeline","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/replays/search":{"post":{"tags":["Replays"],"operationId":"searchReplays","summary":"Find moments across sessions","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["q"],"properties":{"q":{"type":"string"},"filter":{"$ref":"#/components/schemas/Object"}}}}}},"responses":{"200":{"description":"Moments with a time into the session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/replays/ask":{"post":{"tags":["Replays"],"operationId":"askReplays","summary":"Ask a question across sessions","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["question"],"properties":{"question":{"type":"string"},"filter":{"$ref":"#/components/schemas/Object"}}}}}},"responses":{"200":{"description":"An answer with [session, time] citations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/sites/{host}/openapi.json":{"get":{"tags":["Sites"],"operationId":"getSiteOpenApi","summary":"One site's tools as an OpenAPI spec","security":[],"parameters":[{"name":"host","in":"path","required":true,"schema":{"type":"string"},"example":"news.ycombinator.com"}],"responses":{"200":{"description":"OpenAPI 3.1 for the site","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/sites/{host}/call/{tool}":{"post":{"tags":["Sites"],"operationId":"callSiteTool","summary":"Call one of a site's tools","parameters":[{"name":"host","in":"path","required":true,"schema":{"type":"string"}},{"name":"tool","in":"path","required":true,"schema":{"type":"string"}},{"name":"x-unbrowse-deadline-ms","in":"header","required":false,"schema":{"type":"integer","minimum":5000,"maximum":300000,"default":60000},"description":"Answer within this many ms (clamped to 5,000–300,000; default 60,000). Past it the answer is 504 run_timeout; the run keeps going."},{"name":"deadlineMs","in":"query","required":false,"schema":{"type":"integer","minimum":5000,"maximum":300000,"default":60000},"description":"Same as the x-unbrowse-deadline-ms header (the header wins)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"The tool's inputs (see the site's OpenAPI spec). `deadlineMs` here bounds the call like the header, unless the tool takes an input of that name."}}}},"responses":{"200":{"description":"The tool's result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"202":{"description":"The run needs input (`input_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"504":{"description":"run_timeout: the run did not finish within its deadline. It keeps running: poll `GET /api/v1/runs/{runId}` with the runId given. A verified success is billed once when it lands; a failure is never billed. A retry with the same Idempotency-Key joins the same run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunTimeout"}}}}}}},"/api/v1/index":{"post":{"tags":["Indexing"],"operationId":"startIndexJob","summary":"Index a site","description":"Explores the site in the cloud browser and compiles what it finds into capabilities. Follow the job at /api/v1/index/{jobId}.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"focus":{"type":"string","description":"What to look for, in plain words. Only sitemap page types that match it are indexed, none when it names flows (paging, page size, filters, search)."},"maxCapabilities":{"type":"integer","minimum":1,"maximum":12,"description":"At most this many tools in all: declared tools, sitemap page types and recorded flows together. Left out: up to 6 recorded flows plus up to 8 sitemap page types."},"public":{"type":"boolean","description":"Publish the capabilities to the public index."}}}}}},"responses":{"202":{"description":"The job","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"get":{"tags":["Indexing"],"operationId":"listIndexJobs","summary":"Your index jobs","responses":{"200":{"description":"Jobs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/index/{jobId}":{"get":{"tags":["Indexing"],"operationId":"getIndexJob","summary":"Follow an index job","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string","pattern":"^ix_[a-z0-9]+$"}}],"responses":{"200":{"description":"The job","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/learned":{"get":{"tags":["Capabilities"],"operationId":"listLearned","summary":"Capabilities learned in your workspace","responses":{"200":{"description":"Learned capabilities","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/cookies":{"post":{"tags":["Account"],"operationId":"importCookies","summary":"Import browser cookies as kept sessions","description":"Takes cookies exported from the user's own browser (the CLI's `unbrowse cookies sync`) and keeps them as a signed-in session per site, sealed in the vault, so later runs act as the signed-in user. Values are stored, never returned.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["cookies"],"properties":{"cookies":{"type":"array","items":{"type":"object","required":["domain","name","value"],"properties":{"domain":{"type":"string","description":"The cookie's domain, e.g. .example.com"},"name":{"type":"string"},"value":{"type":"string"},"path":{"type":"string"},"secure":{"type":"boolean"},"httpOnly":{"type":"boolean"},"expires":{"type":"integer","description":"Unix seconds; 0 = session cookie."}}}}}}}}},"responses":{"200":{"description":"How many sites and cookies were kept","content":{"application/json":{"schema":{"type":"object","properties":{"sites":{"type":"integer"},"cookies":{"type":"integer"},"origins":{"type":"array","items":{"$ref":"#/components/schemas/Object"}}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/apps":{"get":{"tags":["Apps & tools"],"operationId":"listApps","summary":"Apps and the tools in each","description":"The workspace's own tools and the public ones it uses, grouped by app (registrable domain), with whether each is switched on and, for its own, whether it is published. Also the workspace's scopes with their MCP URLs.","responses":{"200":{"description":"Apps, tools and scopes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/scopes":{"get":{"tags":["Apps & tools"],"operationId":"listScopes","summary":"Tool scopes","responses":{"200":{"description":"Scopes, each with its MCP URLs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"tags":["Apps & tools"],"operationId":"saveScope","summary":"Create or update a scope (by slug)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolScope"}}}},"responses":{"201":{"description":"The scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolScope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/scopes/{slug}":{"get":{"tags":["Apps & tools"],"operationId":"getScope","summary":"One scope","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]{0,39}$"}}],"responses":{"200":{"description":"The scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolScope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"put":{"tags":["Apps & tools"],"operationId":"updateScope","summary":"Update a scope","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]{0,39}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolScope"}}}},"responses":{"200":{"description":"The scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolScope"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"delete":{"tags":["Apps & tools"],"operationId":"deleteScope","summary":"Delete a scope","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]{0,39}$"}}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/tools/{capabilityId}/{action}":{"post":{"tags":["Apps & tools"],"operationId":"changeTool","summary":"Switch a tool on or off, or unpublish / republish one you learned","description":"enable / disable apply to every connection in the workspace. unpublish takes down the public copy this workspace published and keeps the tool private until republish; a copy someone else published stays up.","parameters":[{"name":"capabilityId","in":"path","required":true,"schema":{"type":"string"}},{"name":"action","in":"path","required":true,"schema":{"type":"string","enum":["enable","disable","unpublish","republish"]}}],"responses":{"200":{"description":"The tool's new state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/workspace/sharing":{"get":{"tags":["Account"],"operationId":"getSharing","summary":"Whether this workspace's learned routes are shared to the public registry, and why","description":"Acts on the workspace of the API key (or sign-in) making the call. Free workspaces share by default; a workspace that has ever paid is private by default and shares only after opting in. Run results and inputs are never published.","responses":{"200":{"description":"The effective setting","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sharing"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"put":{"tags":["Account"],"operationId":"setSharing","summary":"Opt in to or out of sharing learned routes to the public registry","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["shareLearned"],"properties":{"shareLearned":{"type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"The effective setting","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sharing"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/workspace/session-reuse":{"get":{"tags":["Account"],"operationId":"getSessionReuse","summary":"Whether runs reuse this workspace's kept signed-in sessions automatically, and why","description":"Acts on the workspace of the API key (or sign-in) making the call. On by default: a site you are signed in to (a kept session, sealed in the vault) is reused by runs, scrapes and browse sessions without asking. A site set to Never in the password manager is never reused; one set to Ask me asks first. Turning it off refuses every site and asks no one.","responses":{"200":{"description":"The effective setting","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReuse"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"put":{"tags":["Account"],"operationId":"setSessionReuse","summary":"Turn automatic reuse of kept sign-ins off (or back on) for this workspace","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["reuse"],"properties":{"reuse":{"type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"The effective setting","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReuse"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/usage":{"get":{"tags":["Account"],"operationId":"getUsage","summary":"This month's metered usage","responses":{"200":{"description":"Verified calls, quota and what remains","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/api/v1/me":{"get":{"tags":["Account"],"operationId":"getMe","summary":"The signed-in user and workspace","responses":{"200":{"description":"The principal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}}},"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"Authorization code with PKCE (S256). Clients may register dynamically at /oauth/register. Discovery: /.well-known/oauth-authorization-server; the REST API's protected-resource metadata is /.well-known/oauth-protected-resource/api.","flows":{"authorizationCode":{"authorizationUrl":"https://alternativeto-net-mcp.unbrowse.ai/authorize","tokenUrl":"https://alternativeto-net-mcp.unbrowse.ai/oauth/token","refreshUrl":"https://alternativeto-net-mcp.unbrowse.ai/oauth/token","scopes":{"unbrowse":"Run tasks and read results on the user's behalf, with their kept logins."}}}},"apiKey":{"type":"http","scheme":"bearer","description":"An Unbrowse API key (create one in the console at https://unbrowse.ai/app)."}},"responses":{"Error":{"description":"An error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Missing or invalid credentials. The WWW-Authenticate header names the protected-resource metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Object":{"type":"object","additionalProperties":true},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"additionalProperties":true}},"additionalProperties":true},"RunTimeout":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","runId","poll"],"properties":{"code":{"type":"string","const":"run_timeout"},"message":{"type":"string"},"runId":{"type":"string","description":"Poll this id at GET /api/v1/runs/{runId} (MCP: unbrowse.inspect)."},"deadlineMs":{"type":"integer"},"poll":{"type":"string","examples":["GET /api/v1/runs/prun_1a2b3c"]}}}}},"Sharing":{"type":"object","required":["workspaceId","shareLearned","paid","reason"],"properties":{"workspaceId":{"type":"string"},"shareLearned":{"type":"boolean","description":"Effective: whether a learned public read-only route is shared after its first verified run."},"explicit":{"type":["boolean","null"],"description":"What the workspace set; null when it never chose (the plan default applies)."},"paid":{"type":"boolean","description":"The workspace has paid credits or a completed purchase."},"reason":{"type":"string","examples":["paid workspace: private by default","free workspace: shared by default (turn it off any time)"]},"shared":{"type":"integer","description":"Routes this workspace has shared so far."},"published":{"type":"string","description":"What sharing publishes: the scrubbed route only, never run results or inputs."}}},"SessionReuse":{"type":"object","required":["workspaceId","reuse","reason"],"properties":{"workspaceId":{"type":"string"},"reuse":{"type":"boolean","description":"Effective: whether kept signed-in sessions are reused automatically (sites set to Never or Ask me excepted)."},"explicit":{"type":["boolean","null"],"description":"What the workspace set; null when it never chose (on by default)."},"reason":{"type":"string","examples":["on by default: kept sign-ins are reused automatically","turned off for this workspace: no kept sign-in is reused, and no one is asked"]},"never":{"type":"array","items":{"type":"string"},"description":"Sites set to Never: their kept sign-in is never reused."},"ask":{"type":"array","items":{"type":"string"},"description":"Sites set to Ask me: each reuse needs your approval."},"change":{"type":"string"}}},"ToolScope":{"type":"object","required":["slug"],"description":"A named set of apps and tools. An MCP client at /mcp/{slug} (or /mcp?scope={slug}) lists and routes to only these; /mcp?apps=a.com,b.com is the ad-hoc form.","properties":{"slug":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]{0,39}$"},"name":{"type":"string"},"apps":{"type":"array","items":{"type":"string"},"description":"Registrable domains (github.com); every tool on them is in scope."},"tools":{"type":"array","items":{"type":"string"},"description":"Capability ids, on top of the apps."},"core":{"description":"Which Unbrowse tools the connection keeps.","oneOf":[{"type":"string","enum":["all","run_only"]},{"type":"array","items":{"type":"string"}}]},"discoverPublic":{"type":"boolean","description":"Let discover search the whole public registry, beyond the scope's apps."},"urls":{"type":"object","readOnly":true,"properties":{"mcp":{"type":"string"},"mcpQuery":{"type":"string"}}}}},"RunRequest":{"type":"object","required":["idempotencyKey"],"properties":{"task":{"type":"string","description":"What to do, in plain words. Unbrowse picks the capability."},"capability":{"type":"string","description":"A capability id to run instead of routing the task (from /api/v1/capabilities/search)."},"targetUrl":{"type":"string","format":"uri","description":"The site to do it on, when the task does not name one."},"input":{"type":"object","additionalProperties":true,"description":"The capability's inputs."},"accountRefs":{"type":"array","items":{"type":"string"},"description":"Which kept logins to use."},"interactionMode":{"type":"string","enum":["interactive","unattended","external_handler"],"description":"unattended: a check nobody can clear fails instead of waiting."},"idempotencyKey":{"type":"string","description":"Repeat a request with the same key to get the same run."},"deadlineMs":{"type":"integer","minimum":5000,"maximum":300000,"default":60000,"description":"Answer within this many ms; past it 504 run_timeout with a runId to poll (the run keeps going). The x-unbrowse-deadline-ms header wins."},"egress":{"type":"string","enum":["server","client"],"default":"server","description":"client: you send the site requests from your own IP (see /api/v1/egress/{egressId})."},"select":{"type":"array","items":{"type":"string"},"example":["results[].{id,title,price}","total"],"description":"Keep only these parts of the result. Dots walk keys, [] maps over a list, [n] takes one item, a final {a,b} keeps several keys. Applied to the answer after the run is verified; billing is the same. Paths that matched nothing come back in `selectMissing`; a malformed path is a 400 invalid_input naming it. Results over 40,000 characters are shortened (`truncated`), so select what you need."}}},"EgressRequest":{"type":"object","required":["id","method","url","headers","redirect","curl"],"properties":{"id":{"type":"string","description":"Answer with this requestId."},"method":{"type":"string"},"url":{"type":"string","format":"uri"},"headers":{"type":"object","additionalProperties":{"type":"string"}},"body":{"type":"string"},"bodyEncoding":{"type":"string","enum":["text","base64"]},"redirect":{"type":"string","enum":["follow","manual"],"description":"manual: do not follow redirects; return the 3xx as is."},"curl":{"type":"string","description":"The same request as a curl command (-i prints what to post back)."}}},"EgressStep":{"type":"object","required":["status","egressId","requests"],"properties":{"status":{"type":"string","enum":["egress_required"]},"egressId":{"type":"string"},"requests":{"type":"array","items":{"$ref":"#/components/schemas/EgressRequest"}},"answer":{"$ref":"#/components/schemas/Object"}}},"EgressResponse":{"type":"object","required":["status"],"properties":{"status":{"type":"integer","minimum":100,"maximum":599},"headers":{"description":"As [name, value] pairs (keeps repeated headers such as set-cookie) or an object.","oneOf":[{"type":"array","items":{"type":"array","items":{"type":"string"},"minItems":2,"maxItems":2}},{"type":"object","additionalProperties":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]}}]},"body":{"type":"string","description":"The body, decoded (no content-encoding). Up to 10 MB."},"bodyEncoding":{"type":"string","enum":["text","base64"],"default":"text"},"url":{"type":"string","format":"uri","description":"The final URL, when redirects were followed."}}},"Run":{"type":"object","required":["runId","status"],"properties":{"runId":{"type":"string"},"status":{"type":"string","enum":["accepted","working","input_required","succeeded","failed","outcome_unknown","cancelled","expired"]},"capabilityId":{"type":["string","null"]},"phase":{"type":"string"},"stateRevision":{"type":"integer"},"result":{"description":"The verified result (status succeeded)."},"requirements":{"type":"array","items":{"$ref":"#/components/schemas/Object"},"description":"What the run needs (status input_required)."},"error":{"$ref":"#/components/schemas/Object"},"verified":{"type":"boolean"}},"additionalProperties":true}}}}