{"openapi":"3.1.0","info":{"title":"Unbrowse API","version":"1.1.0","description":"Jev-powered private tool search, deterministic workflows, remote browser indexing, sealed credentials and OAuth S256 PKCE. New accounts receive $1 free credits (10,000 calls) once; prepaid packs cost $10 per 100,000 calls. Each admitted search, index, compile or execute request costs one credit; catalog inspection is free. Remote indexing observes with the existing browser agent; workflow compilation and replay use observed requests. Replay retains a browser session for authentication."},"externalDocs":{"description":"Search and execution guide","url":"https://api.unbrowse.ai/docs"},"servers":[{"url":"https://api.unbrowse.ai"}],"paths":{"/v1/auth/register":{"post":{"operationId":"register","summary":"Create an account. Username is not an email identity.","security":[],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"username":{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]{2,63}$"},"password":{"type":"string","minLength":12,"maxLength":256,"writeOnly":true}},"required":["username","password"],"additionalProperties":false}}}},"responses":{"201":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/v1/auth/login":{"post":{"operationId":"login","summary":"Sign in for a one-hour owner token.","security":[],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"username":{"type":"string"},"password":{"type":"string","writeOnly":true}},"required":["username","password"],"additionalProperties":false}}}},"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/oauth/clients":{"post":{"operationId":"registerClient","summary":"Register a public OAuth client. Requires owner token.","security":[{"oauth2":["tools:read"]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_name":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string","format":"uri"},"minItems":1,"maxItems":5}},"required":["client_name","redirect_uris"],"additionalProperties":false}}}},"responses":{"201":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/oauth/token":{"post":{"operationId":"exchangeToken","summary":"Exchange one-use S256 authorization code or rotate refresh token.","security":[],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"grant_type":{"enum":["authorization_code","refresh_token"]},"code":{"type":"string"},"code_verifier":{"type":"string"},"client_id":{"type":"string"},"redirect_uri":{"type":"string"},"refresh_token":{"type":"string","writeOnly":true}},"required":["grant_type","client_id"],"additionalProperties":false}}}},"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/oauth/revoke":{"post":{"operationId":"revokeToken","summary":"Revoke the current bearer token.","security":[{"oauth2":["tools:read"]}],"parameters":[],"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/v1/tools/search":{"post":{"operationId":"searchTools","summary":"Search private tools by intent using Jev. Ranked callable matches, an untested candidate, or needs_observation; unavailable on invalid model evidence. Optional domain restriction. One credit; no website execution.","security":[{"oauth2":["tools:read"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128},"description":"Reuse for retries. Different inputs with the same key return 409."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"intent":{"type":"string","minLength":1,"maxLength":2000},"domain":{"type":"string","example":"example.com"}},"required":["intent"],"additionalProperties":false}}}},"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object","required":["status","cost"],"properties":{"status":{"enum":["completed","uncertain"]},"cost":{"type":"integer","const":1},"replayed":{"type":"boolean"},"result":{"type":"object","properties":{"status":{"enum":["matched","candidate","needs_observation","unavailable"]},"tools":{"type":"array","maxItems":10,"items":{"type":"object","properties":{"id":{"type":"string"},"score":{"type":"number","minimum":0.9,"maximum":1},"endpoint":{"type":"string"},"inputs":{"type":"array","items":{"type":"object"}},"outputs":{"type":"array","items":{"type":"object"}}}}},"candidate":{"type":"object"},"evidence":{"type":"array","items":{"type":"object"}},"index_endpoint":{"type":"string","const":"/v1/index"},"reason":{"type":"string"},"error":{"type":"string"},"message":{"type":"string"}}}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}},"description":"Read result.status after an outer completed receipt. Search is account-private and never browses the web. GET /v1/tools formerly returned a catalog; use GET /v1/tools/catalog for that response. All search forms share the same operation key. A saved unavailable or uncertain result is replayed unchanged; a fresh attempt requires a new key and credit."}},"/v1/tool-router":{"post":{"operationId":"routeTools","summary":"Alias of searchTools; same result and idempotency ledger. Search private tools by intent using Jev. Ranked callable matches, an untested candidate, or needs_observation; unavailable on invalid model evidence. Optional domain restriction. One credit; no website execution.","security":[{"oauth2":["tools:read"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128},"description":"Reuse for retries. Different inputs with the same key return 409."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"intent":{"type":"string","minLength":1,"maxLength":2000},"domain":{"type":"string","example":"example.com"}},"required":["intent"],"additionalProperties":false}}}},"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object","required":["status","cost"],"properties":{"status":{"enum":["completed","uncertain"]},"cost":{"type":"integer","const":1},"replayed":{"type":"boolean"},"result":{"type":"object","properties":{"status":{"enum":["matched","candidate","needs_observation","unavailable"]},"tools":{"type":"array","maxItems":10,"items":{"type":"object","properties":{"id":{"type":"string"},"score":{"type":"number","minimum":0.9,"maximum":1},"endpoint":{"type":"string"},"inputs":{"type":"array","items":{"type":"object"}},"outputs":{"type":"array","items":{"type":"object"}}}}},"candidate":{"type":"object"},"evidence":{"type":"array","items":{"type":"object"}},"index_endpoint":{"type":"string","const":"/v1/index"},"reason":{"type":"string"},"error":{"type":"string"},"message":{"type":"string"}}}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}},"description":"Read result.status after an outer completed receipt. Search is account-private and never browses the web. GET /v1/tools formerly returned a catalog; use GET /v1/tools/catalog for that response. All search forms share the same operation key. A saved unavailable or uncertain result is replayed unchanged; a fresh attempt requires a new key and credit."}},"/v1/tools":{"get":{"operationId":"searchToolsByQuery","summary":"Search private tools by intent using Jev. Ranked callable matches, an untested candidate, or needs_observation; unavailable on invalid model evidence. Optional domain restriction. One credit; no website execution.","security":[{"oauth2":["tools:read"]}],"parameters":[{"name":"intent","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":2000}},{"name":"domain","in":"query","required":false,"schema":{"type":"string","example":"example.com"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128},"description":"Reuse for retries. Different inputs with the same key return 409."}],"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object","required":["status","cost"],"properties":{"status":{"enum":["completed","uncertain"]},"cost":{"type":"integer","const":1},"replayed":{"type":"boolean"},"result":{"type":"object","properties":{"status":{"enum":["matched","candidate","needs_observation","unavailable"]},"tools":{"type":"array","maxItems":10,"items":{"type":"object","properties":{"id":{"type":"string"},"score":{"type":"number","minimum":0.9,"maximum":1},"endpoint":{"type":"string"},"inputs":{"type":"array","items":{"type":"object"}},"outputs":{"type":"array","items":{"type":"object"}}}}},"candidate":{"type":"object"},"evidence":{"type":"array","items":{"type":"object"}},"index_endpoint":{"type":"string","const":"/v1/index"},"reason":{"type":"string"},"error":{"type":"string"},"message":{"type":"string"}}}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}},"description":"Read result.status after an outer completed receipt. Search is account-private and never browses the web. GET /v1/tools formerly returned a catalog; use GET /v1/tools/catalog for that response. All search forms share the same operation key. A saved unavailable or uncertain result is replayed unchanged; a fresh attempt requires a new key and credit."}},"/v1/tools/catalog":{"get":{"operationId":"inspectToolCatalog","summary":"Inspect private traces and tools with verification status. Free; no Jev ranking or secret values.","security":[{"oauth2":["tools:read"]}],"parameters":[],"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/v1/tools/{toolId}":{"get":{"operationId":"getTool","summary":"Read a private tool and its input slots.","security":[{"oauth2":["tools:read"]}],"parameters":[{"name":"toolId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/v1/tools/{toolId}/execute":{"post":{"operationId":"executeTool","summary":"Execute an observed workflow. Explicit confirmation required for mutations. One credit.","security":[{"oauth2":["tools:execute"]}],"parameters":[{"name":"toolId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128},"description":"Reuse for retries. Different inputs with the same key return 409."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"inputs":{"type":"object","additionalProperties":{"type":["string","number","boolean","null"]}},"intent":{"type":"string"},"allow_mutation":{"type":"boolean","default":false}},"required":["intent"],"additionalProperties":false}}}},"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/v1/tools/prepare":{"post":{"operationId":"prepareTool","summary":"Compile a captured request and observed dependencies into a candidate tool. One credit.","security":[{"oauth2":["tools:execute"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128},"description":"Reuse for retries. Different inputs with the same key return 409."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"trace_id":{"type":"string"},"target":{"type":"string"},"intent":{"type":"string"},"dependencies":{"type":"array","items":{"type":"string"},"maxItems":12}},"required":["trace_id","target","intent"],"additionalProperties":false}}}},"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/v1/index":{"post":{"operationId":"indexWorkflow","summary":"Observe a workflow using the tenant remote browser and retain its private trace. One credit.","security":[{"oauth2":["browser:write"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128},"description":"Reuse for retries. Different inputs with the same key return 409."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"intent":{"type":"string"},"browser":{"enum":["remote"],"default":"remote"}},"required":["url","intent"],"additionalProperties":false}}}},"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/v1/accounts":{"get":{"operationId":"listAccounts","summary":"List saved credential names and timestamps. Values are never returned.","security":[{"oauth2":["accounts:write"]}],"parameters":[],"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/v1/accounts/{name}":{"put":{"operationId":"saveCredential","summary":"Create or replace a sealed credential. Browser uses {{secret:name}}.","security":[{"oauth2":["accounts:write"]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]{0,63}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"value":{"type":"string","minLength":1,"maxLength":4096,"writeOnly":true}},"required":["value"],"additionalProperties":false}}}},"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}},"delete":{"operationId":"deleteCredential","summary":"Delete a saved credential. Existing cookies are cleared separately.","security":[{"oauth2":["accounts:write"]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]{0,63}$"}}],"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/v1/browser":{"delete":{"operationId":"forgetBrowser","summary":"Stop the tenant browser and clear its cookies.","security":[{"oauth2":["browser:write"]}],"parameters":[],"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/v1/browser/stop":{"post":{"operationId":"stopBrowser","summary":"Stop the tenant browser while preserving its profile.","security":[{"oauth2":["browser:write"]}],"parameters":[],"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/v1/browser/view":{"get":{"operationId":"viewBrowser","summary":"Get an owner browser viewing link. Treat the link as private.","security":[{"oauth2":["browser:write"]}],"parameters":[],"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/v1/usage":{"get":{"operationId":"usage","summary":"Read prepaid balance and debited call count.","security":[{"oauth2":["tools:read"]}],"parameters":[],"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}},"/v1/billing/checkout":{"post":{"operationId":"checkout","summary":"Buy 100,000 calls for USD 10. Owner token required. Not charged until payment.","security":[{"oauth2":["tools:read"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128},"description":"Reuse for retries. Different inputs with the same key return 409."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Successful response; execution receipts include status, result, cost, and replayed on retries.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input"},"401":{"description":"Invalid or expired bearer token"},"402":{"description":"Insufficient prepaid credits"},"403":{"description":"Scope or mutation authorization missing"},"409":{"description":"Conflicting idempotency key or username"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required provider is not configured"}}}}},"components":{"securitySchemes":{"oauth2":{"type":"oauth2","flows":{"authorizationCode":{"authorizationUrl":"https://api.unbrowse.ai/oauth/authorize","tokenUrl":"https://api.unbrowse.ai/oauth/token","refreshUrl":"https://api.unbrowse.ai/oauth/token","scopes":{"tools:read":"Discover private tools","tools:execute":"Compile and execute workflows","browser:write":"Observe workflows and manage browser","accounts:write":"Manage sealed website credentials"}}}}}}}