{"openapi":"3.1.0","info":{"title":"looot API","version":"0.1.0","description":"Discover, inspect, run, and pay for real (or fixture) provider operations through one bearer token.\n\n## Errors\nEvery error answers application/json with the Error schema: {\"error\":{\"code\",\"message\",\"requestId\"}}. It is not RFC 9457 problem+json. Branch on error.code. Some codes add fields, such as retryAfterSeconds and limit on a 429. POST /v1/runs can answer 201 with status \"failed\": read the run, not only the status code.\n\n## Rate limits\nRequests spend token buckets: one per client address before authentication, one per credential after it. Each limited response carries X-RateLimit-Limit and X-RateLimit-Remaining, and the IETF fields from draft-ietf-httpapi-ratelimit-headers: RateLimit-Policy: \"<policy>\";q=<bucket size>;w=<seconds an empty bucket takes to refill> and RateLimit: \"<policy>\";r=<remaining>;t=<seconds until the bucket is full>. A 429 carries Retry-After in seconds; wait that long and send the same request again.\n\n## Versioning and deprecation\nEvery path is under /v1, and /v1 is stable. Changes inside /v1 are additive: new operations, new optional request fields, new response fields and new error codes. Clients must ignore response fields they do not know. A breaking change ships under a new version prefix, and /v1 keeps answering next to it. Before an operation is removed it is marked deprecated: true in this document, and its responses carry a Deprecation header (RFC 9745) with the date it was deprecated, a Sunset header (RFC 8594) with the date it stops answering, and a Link header to its replacement. info.version is the version of this document. No operation is deprecated today.","termsOfService":"https://looot.ai/terms","contact":{"name":"looot","url":"https://looot.ai/contact"}},"servers":[{"url":"https://api.looot.ai","description":"Public API (default)"}],"security":[{"bearerAuth":[]}],"paths":{"/v1/discover":{"get":{"summary":"Discover operations","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["candidates","meta"],"properties":{"candidates":{"type":"array","description":"Ranked candidates. detail=title answers only the title fields (rank, endpointId, provider, name, capability, category, estimatedPrice, priceBasis and a few optional ones)","items":{"type":"object","required":["rank","endpointId","provider","name","capability","category","estimatedPrice","priceBasis"],"properties":{"rank":{"type":"integer"},"endpointId":{"type":"string"},"provider":{"type":"string"},"name":{"type":"string"},"capability":{"type":"string"},"category":{"type":"string"},"summary":{"type":"string"},"reliability":{"type":"string"},"reason":{"type":"string"},"estimatedPrice":{"type":"number"},"priceBasis":{"type":"string"},"eligibility":{"type":"string"},"match":{"type":"object","properties":{"requestedMode":{"type":"string"},"resolvedMode":{"type":"string"},"matchedFields":{"type":"array","items":{"type":"string"}},"relevanceScore":{"type":"number"},"usedFallback":{"type":"boolean"}}},"ranking":{"type":"object"},"score":{"type":"object","properties":{"overall":{"type":"number"},"components":{"type":"object"}}},"mock":{"type":"boolean"},"verified":{"type":"boolean"},"keyless":{"type":"boolean"},"runnableNow":{"type":"boolean"},"access":{"type":"string"},"costPerSuccessUsd":{"type":["number","null"]},"async":{"type":"boolean"},"works":{"type":"object"},"sourceCapability":{"type":"string"},"credential":{"type":"string"}}}},"meta":{"type":"object","required":["requestedMode","resolvedMode","ranking","totalEligible","totalAfterThreshold","resultCount","warnings"],"properties":{"requestedMode":{"type":"string"},"resolvedMode":{"type":"string"},"ranking":{"type":"string"},"totalEligible":{"type":"integer"},"totalAfterThreshold":{"type":"integer"},"resultCount":{"type":"integer"},"warnings":{"type":"array","items":{"type":"string"}},"prefer":{"type":"string"}}},"jobInputs":{"type":"object","description":"Per job, per input name, which endpoints accept it; present only when non-empty"}}}}}},"401":{"description":"unauthorized: a valid bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limit_exceeded: wait Retry-After seconds and send the same request again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before the next request fits the bucket","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Bucket size (legacy header, kept)","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the bucket (legacy header, kept)","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";q=<bucket size>;w=<seconds an empty bucket takes to refill>","schema":{"type":"string"}},"RateLimit":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";r=<remaining>;t=<seconds until the bucket is full>","schema":{"type":"string"}}}},"500":{"description":"internal_error: an unexpected failure; the message is masked, quote requestId when reporting it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"discoverOperations","description":"Rank catalog operations for a plain-words intent or a capability. Answers candidates with price, access and ranking evidence, plus meta with counts. detail=title answers short rows."}},"/v1/catalog/search":{"get":{"summary":"Ranked full-text catalog search, with capability expansion and a stemmed-token fallback so a long natural-language query is never empty","description":"The same search core answers MCP `search` (10 title rows by default) and MCP search_catalog (50 full rows by default, like this route). A title row is a subset of this route's row: endpointId, provider, name, capability, category, estimatedPrice, priceBasis, access, executionMode, costPerSuccessUsd (facts.costPerSuccessUsd), async (facts.async), works, sourceCapability and credential, in the same order for the same q, limit and offset for a customer token. A platform operator token differs: this route always includes unavailable rows, while MCP honors an explicit filters.includeUnavailable false.","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200}},{"name":"offset","in":"query","description":"Where the page starts in the ranked list; pass the previous page's nextOffset (null on the last page).","schema":{"type":"integer","minimum":0}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"platform","in":"query","schema":{"type":"string"}},{"name":"provider","in":"query","schema":{"type":"string"}},{"name":"capability","in":"query","schema":{"type":"string"}},{"name":"keyless","in":"query","schema":{"type":"boolean"}},{"name":"verified","in":"query","schema":{"type":"boolean"}},{"name":"mock","in":"query","description":"true/false excludes the other kind; omitted keeps both but real providers still rank above mocks","schema":{"type":"boolean"}},{"name":"maxPriceMicros","in":"query","schema":{"type":"integer","minimum":0}},{"name":"hidden","in":"query","schema":{"type":"boolean"}},{"name":"prefer","in":"query","description":"How providers are ordered inside a job: balanced (default), cheapest, reliable or fastest. Any other value is a 400 validation_error. Every item's facts carry it and the body echoes it; it changes the order only once the gateway serves the shared ranking.","schema":{"type":"string","enum":["cheapest","reliable","fastest","balanced"]}}],"responses":{"200":{"description":"Ranked catalog items (each carrying mock, verified, keyless, runnableNow, stats, access, matchedBy, facts, works, credential and sourceCapability; capability is the resolved job id), same shape as the listing, plus the prefer value used. An empty page may carry warnings (no_supply_for_job) or priceHint (price_above_max: maxPriceMicros removed every endpoint that does the named job; it names the cheapest)","content":{"application/json":{"schema":{"type":"object","required":["generatedAt","workspaceId","query","endpoints","total","offset","nextOffset","expandedCapabilities"],"properties":{"generatedAt":{"type":"string","format":"date-time"},"workspaceId":{"type":"string"},"query":{"type":"string"},"endpoints":{"type":"array","items":{"allOf":[{"type":"object","required":["endpointId","providerId","provider","capability","category","platform","name","description","job","executionMode","eligibility","price","estimatedPrice","priceBasis","keyless","mock","runnableNow","verified","access","availability"],"properties":{"endpointId":{"type":"string"},"providerId":{"type":"string"},"provider":{"type":"string"},"capability":{"type":"string"},"sourceCapability":{"type":"string"},"category":{"type":"string"},"platform":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"version":{"type":"number"},"publishedAt":{"type":"string"},"job":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"subject":{"type":"string"},"kind":{"type":"string"},"platformLabel":{"type":"string"},"categoryLabel":{"type":"string"},"hidden":{"type":"boolean"},"known":{"type":"boolean"}}},"executionMode":{"type":"string"},"eligibility":{"type":"string"},"authType":{"type":"string"},"price":{"type":"object","description":"All-in price model (platform fee folded into perCall)"},"estimatedPrice":{"type":"number","description":"USD"},"customerPrice":{"type":"number"},"priceBasis":{"enum":["perCall","perResult"]},"unpriced":{"type":"boolean"},"method":{"type":["string","null"]},"path":{"type":["string","null"]},"host":{"type":["string","null"]},"bundleKind":{"enum":["seed","direct","bundle"]},"keyless":{"type":"boolean"},"connected":{"type":"boolean"},"platformSupply":{"type":"boolean"},"readyToRun":{"type":"boolean"},"mock":{"type":"boolean"},"runnableNow":{"type":"boolean"},"verified":{"type":"boolean"},"access":{"enum":["runs_now","needs_your_account","coming_soon"]},"unavailableReason":{"type":["string","null"]},"credential":{"type":"string"},"verifiedAt":{"type":["string","null"]},"stats":{"type":["object","null"],"properties":{"source":{"type":"string"},"window":{"type":"string"},"calls":{"type":"integer"},"successRate":{"type":["number","null"]},"p50Ms":{"type":["number","null"]},"p95Ms":{"type":["number","null"]},"lastSuccessAt":{"type":["string","null"]},"qualified":{"type":"boolean"}}},"observedSuccessRate":{"type":["number","null"]},"observedLatencyMs":{"type":["number","null"]},"sampleSize":{"type":"number"},"examples":{"type":"array","items":{"type":"string"}},"effectClassification":{"type":"string"},"availability":{"enum":["active","draining","disabled"]},"supply":{"type":"object","description":"Present only while the platform account for this provider is out of credit"}}},{"type":"object","required":["matchedBy","facts","works"],"properties":{"matchedBy":{"type":"string"},"facts":{"type":"object","description":"Ranking facts: prefer, job, bucket, pricePerUnitUsd, costPerSuccessUsd, success, p50Ms, async, requiredInputs, lastSuccessAt, source, asOf"},"works":{"type":"object","properties":{"rate":{"type":["number","null"]},"runs":{"type":"integer"},"p50Ms":{"type":["number","null"]},"thin":{"type":"boolean"}}}}}]}},"total":{"type":"integer"},"offset":{"type":"integer"},"nextOffset":{"type":["integer","null"]},"expandedCapabilities":{"type":"array","items":{"type":"string"}},"unsuppliedJobs":{"type":"array","items":{"type":"string"}},"warnings":{"type":"array","items":{"type":"object"}},"prefer":{"enum":["balanced","cheapest","reliable","fastest"]},"priceHint":{"type":"object"},"jobInputs":{"type":"object"}}}}}},"400":{"description":"q is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"catalog:read scope required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"searchCatalog"}},"/v1/catalog/endpoints":{"get":{"summary":"Paged, filtered, faceted catalog listing","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":5000}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":4096}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"platform","in":"query","schema":{"type":"string"}},{"name":"provider","in":"query","schema":{"type":"string"}},{"name":"capability","in":"query","schema":{"type":"string"}},{"name":"keyless","in":"query","schema":{"type":"boolean"}},{"name":"verified","in":"query","schema":{"type":"boolean"}},{"name":"maxPriceMicros","in":"query","schema":{"type":"integer","minimum":0}},{"name":"hidden","in":"query","schema":{"type":"boolean"}},{"name":"facets","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Catalog listing page with nextCursor and, when facets=true, category/platform/provider/capability counts for the filtered set","content":{"application/json":{"schema":{"type":"object","required":["generatedAt","workspaceId","endpoints","providers","counts","nextCursor"],"properties":{"generatedAt":{"type":"string","format":"date-time"},"workspaceId":{"type":"string"},"endpoints":{"type":"array","items":{"type":"object","required":["endpointId","providerId","provider","capability","category","platform","name","description","job","executionMode","eligibility","price","estimatedPrice","priceBasis","keyless","mock","runnableNow","verified","access","availability"],"properties":{"endpointId":{"type":"string"},"providerId":{"type":"string"},"provider":{"type":"string"},"capability":{"type":"string"},"sourceCapability":{"type":"string"},"category":{"type":"string"},"platform":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"version":{"type":"number"},"publishedAt":{"type":"string"},"job":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"subject":{"type":"string"},"kind":{"type":"string"},"platformLabel":{"type":"string"},"categoryLabel":{"type":"string"},"hidden":{"type":"boolean"},"known":{"type":"boolean"}}},"executionMode":{"type":"string"},"eligibility":{"type":"string"},"authType":{"type":"string"},"price":{"type":"object","description":"All-in price model (platform fee folded into perCall)"},"estimatedPrice":{"type":"number","description":"USD"},"customerPrice":{"type":"number"},"priceBasis":{"enum":["perCall","perResult"]},"unpriced":{"type":"boolean"},"method":{"type":["string","null"]},"path":{"type":["string","null"]},"host":{"type":["string","null"]},"bundleKind":{"enum":["seed","direct","bundle"]},"keyless":{"type":"boolean"},"connected":{"type":"boolean"},"platformSupply":{"type":"boolean"},"readyToRun":{"type":"boolean"},"mock":{"type":"boolean"},"runnableNow":{"type":"boolean"},"verified":{"type":"boolean"},"access":{"enum":["runs_now","needs_your_account","coming_soon"]},"unavailableReason":{"type":["string","null"]},"credential":{"type":"string"},"verifiedAt":{"type":["string","null"]},"stats":{"type":["object","null"],"properties":{"source":{"type":"string"},"window":{"type":"string"},"calls":{"type":"integer"},"successRate":{"type":["number","null"]},"p50Ms":{"type":["number","null"]},"p95Ms":{"type":["number","null"]},"lastSuccessAt":{"type":["string","null"]},"qualified":{"type":"boolean"}}},"observedSuccessRate":{"type":["number","null"]},"observedLatencyMs":{"type":["number","null"]},"sampleSize":{"type":"number"},"examples":{"type":"array","items":{"type":"string"}},"effectClassification":{"type":"string"},"availability":{"enum":["active","draining","disabled"]},"supply":{"type":"object","description":"Present only while the platform account for this provider is out of credit"}}}},"providers":{"type":"array","items":{"type":"object","required":["providerId","displayName","status","endpointCount"],"properties":{"providerId":{"type":"string"},"displayName":{"type":"string"},"categoryId":{"type":["string","null"]},"homepageUrl":{"type":["string","null"]},"docsUrl":{"type":["string","null"]},"status":{"type":"string"},"endpointCount":{"type":"integer"}}}},"counts":{"type":"object","required":["endpoints","providers","capabilities","platforms"],"properties":{"endpoints":{"type":"integer"},"providers":{"type":"integer"},"capabilities":{"type":"integer"},"platforms":{"type":"integer"}}},"nextCursor":{"type":["string","null"]},"facets":{"type":"object","description":"Only with facets=true","properties":{"category":{"type":"object","additionalProperties":{"type":"integer"}},"platform":{"type":"object","additionalProperties":{"type":"integer"}},"provider":{"type":"object","additionalProperties":{"type":"integer"}},"capability":{"type":"object","additionalProperties":{"type":"integer"}}}}}}}}},"304":{"description":"Catalog unchanged since If-None-Match"},"403":{"description":"catalog:read scope required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"listCatalogEndpoints","description":"Page through the catalog with filters. Pass nextCursor back as cursor for the next page; facets=true adds counts per category, platform, provider and capability. Answers 304 when If-None-Match matches the ETag."}},"/v1/operations/{endpointId}":{"get":{"summary":"Inspect an operation","responses":{"200":{"description":"Version-pinned operation contract and safe usage hints","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InspectOutput"}}}},"401":{"description":"unauthorized: a valid bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limit_exceeded: wait Retry-After seconds and send the same request again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before the next request fits the bucket","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Bucket size (legacy header, kept)","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the bucket (legacy header, kept)","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";q=<bucket size>;w=<seconds an empty bucket takes to refill>","schema":{"type":"string"}},"RateLimit":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";r=<remaining>;t=<seconds until the bucket is full>","schema":{"type":"string"}}}},"500":{"description":"internal_error: an unexpected failure; the message is masked, quote requestId when reporting it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"inspectOperation","description":"The version-pinned contract of one endpoint: inputs, price, the most a run can cost, and usage hints. Read it before POST /v1/runs."}},"/v1/runs":{"post":{"summary":"Create a run -- idempotencyKey replay returns the existing run (any status) with replayed:true instead of creating a new one","description":"customer-test friction #4 (docs/product/reviews/2026-09-04-customer-test): dispatch is woken immediately for the run's workspace rather than left for the next poll tick, and the run always returns immediately unless `wait` asks otherwise (either as this query parameter or as a body field of the same name -- the query parameter wins if both are given). `wait=true` (or a bare `?wait`) waits up to the default of 20 s; a number is seconds, clamped to [0, 60]. Returns the result inline, in the same run shape this endpoint already returns, once it reaches a terminal status within `wait` seconds. If it is still queued/running when the window ends, returns that queued/running run instead, exactly as with no `wait` at all -- poll it with GET /v1/runs/{runId} or runs_get. A 201 can carry status:\"failed\" (a pre-dispatch denial such as endpoint_not_found or a validation_error) -- check the run's own `status` and `error` fields, never the HTTP status code alone, to know whether it actually ran.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunRequest"}}}},"parameters":[{"name":"wait","in":"query","schema":{"oneOf":[{"type":"boolean"},{"type":"number","minimum":0,"maximum":60}]},"description":"Seconds to wait for a terminal result inline (default 20 when true/bare, max 60). Omit entirely for the pre-existing immediate-return behavior."},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":1},"description":"Alternative to the request body's idempotencyKey field. Either satisfies the (still mandatory) requirement; if both are present, they must be equal or the request is a 400."},{"name":"X-Looot-Agent","in":"header","required":false,"schema":{"type":"string","maxLength":64,"example":"Claude Code"},"description":"Optional. Names the agent or app making this call, so the run shows under it in your usage (for example \"Claude Code\", \"Cursor\", \"Codex\", \"n8n\"). Read for analytics only: it never changes access, price, limits or the response. A name we do not know is recorded as Other; only the first 64 characters are read and the raw value is never stored."}],"responses":{"201":{"description":"Run created (or the existing run replayed, any status, with replayed:true). A 201 is not itself success -- a pre-dispatch denial (endpoint_not_found, validation_error) also answers 201 with status:\"failed\" and a populated error; read the body, not the status code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"402":{"description":"Out of balance -- the run was blocked before dispatch, never billed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","requestId"],"properties":{"code":{"type":"string","const":"insufficient_balance"},"message":{"type":"string"},"requestId":{"type":"string"}}},"balanceMicros":{"type":"integer"},"estimatedCostMicros":{"type":"integer"},"topUpUrl":{"type":"string","nullable":true},"topUp":{"type":"object","properties":{"minimumUsd":{"type":"number"},"suggestedUsd":{"type":"number"},"checkoutUrl":{"type":"string","nullable":true},"dashboardUrl":{"type":"string"},"message":{"type":"string"},"reason":{"type":"string","enum":["billing_disabled","payment_processor_not_configured","operator_workspace","read_only_token","rate_limited","checkout_failed","stripe_timeout","amount_out_of_range","balance_low","balance_sufficient"]}},"required":["minimumUsd","suggestedUsd","checkoutUrl","dashboardUrl","message"]}},"required":["error","balanceMicros","estimatedCostMicros","topUpUrl","topUp"]}}}},"409":{"description":"Idempotency-key conflict -- a request already exists for this key that this one does not match","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (execute class, too_many_inflight_runs; or run_rate_limited when the gateway has a per-workspace runs-a-minute budget on, with limit and retryAfterSeconds and no inflight) -- see Retry-After and X-RateLimit-* response headers","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","requestId"],"properties":{"code":{"type":"string","const":"too_many_inflight_runs"},"message":{"type":"string"},"requestId":{"type":"string"}}},"inflight":{"type":"integer"},"limit":{"type":"integer"},"retryAfterSeconds":{"type":"integer"}},"required":["error","inflight","limit","retryAfterSeconds"]},{"type":"object","properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","requestId"],"properties":{"code":{"type":"string","const":"run_rate_limited"},"message":{"type":"string"},"requestId":{"type":"string"}}},"limit":{"type":"integer"},"retryAfterSeconds":{"type":"integer"}},"required":["error","limit","retryAfterSeconds"]}]}}},"headers":{"Retry-After":{"description":"Seconds to wait before the next request fits the bucket","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Bucket size (legacy header, kept)","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the bucket (legacy header, kept)","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";q=<bucket size>;w=<seconds an empty bucket takes to refill>","schema":{"type":"string"}},"RateLimit":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";r=<remaining>;t=<seconds until the bucket is full>","schema":{"type":"string"}}}}},"operationId":"createRun"},"get":{"summary":"List runs -- bounded summaries (runId, endpointId, providerId, status, providerResponseStatus, createdAt, completedAt, actualCost, error, resultBytes, and servedEndpointId/servedProviderId (the endpoint and provider that answered; absent when none did)); the full result payload stays on GET /v1/runs/{runId}; includeResult=true opts back in","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["runs","nextCursor"],"properties":{"runs":{"type":"array","description":"Run summaries; with includeResult=true each item is the full Run","items":{"anyOf":[{"type":"object","required":["runId","endpointId","providerId","status","providerResponseStatus","createdAt","completedAt","actualCost","error","resultBytes","outcome"],"properties":{"runId":{"type":"string"},"endpointId":{"type":"string"},"providerId":{"type":["string","null"]},"status":{"enum":["queued","running","completed","failed","blocked","stopped","reconciliation_pending","pending_provider"]},"providerResponseStatus":{"enum":["ok","provider_error","timeout","not_yet_called"]},"createdAt":{"type":"string"},"completedAt":{"type":["string","null"]},"actualCost":{"type":["number","null"]},"error":{"type":["object","null"],"description":"Set only on a failed or blocked run (RunErrorView, src/runs-error-view.ts)","required":["code","message","whoseError","retryable"],"properties":{"code":{"type":"string"},"providerStatus":{"type":["integer","null"]},"message":{"type":"string"},"requestId":{"type":["string","null"]},"whoseError":{"enum":["provider","gateway","customer"]},"retryable":{"type":"boolean"},"retryHint":{"type":["string","null"]},"details":{"type":"object"},"providerMessage":{"type":"string"}}},"resultBytes":{"type":"integer"},"outcome":{"enum":["hit","weak","miss","error","rejected","skipped","pending"]},"job":{"type":"string"},"servedEndpointId":{"type":"string"},"servedProviderId":{"type":["string","null"]}}},{"$ref":"#/components/schemas/Run"}]}},"nextCursor":{"type":["string","null"],"description":"Pass back as cursor; null on the last page"},"olderRunsArchived":{"const":true,"description":"Present only when older runs were archived"}}}}}},"401":{"description":"unauthorized: a valid bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limit_exceeded: wait Retry-After seconds and send the same request again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before the next request fits the bucket","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Bucket size (legacy header, kept)","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the bucket (legacy header, kept)","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";q=<bucket size>;w=<seconds an empty bucket takes to refill>","schema":{"type":"string"}},"RateLimit":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";r=<remaining>;t=<seconds until the bucket is full>","schema":{"type":"string"}}}},"500":{"description":"internal_error: an unexpected failure; the message is masked, quote requestId when reporting it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"listRuns","description":"Recent runs of this workspace as bounded summaries, newest first. The full result payload stays on GET /v1/runs/{runId} unless includeResult=true."}},"/v1/runs/{runId}":{"get":{"summary":"Get a run -- on a failed run, error carries { code, providerStatus, message, requestId, whoseError, retryable, retryHint }, never secrets or raw provider headers","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"401":{"description":"unauthorized: a valid bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limit_exceeded: wait Retry-After seconds and send the same request again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before the next request fits the bucket","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Bucket size (legacy header, kept)","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the bucket (legacy header, kept)","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";q=<bucket size>;w=<seconds an empty bucket takes to refill>","schema":{"type":"string"}},"RateLimit":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";r=<remaining>;t=<seconds until the bucket is full>","schema":{"type":"string"}}}},"500":{"description":"internal_error: an unexpected failure; the message is masked, quote requestId when reporting it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"description":"2026-09-27 (additive): a completed run can carry an optional `normalized` object next to `result`: { job, endpointId, fields, missing, ambiguous, unmapped, providerValues, verdict, verdictReason, mapVerified }, with fixed field names per job and one email status vocabulary (valid, invalid, catch_all, risky, unknown). Present only when the gateway has it turned on and the answering endpoint has an output map; absent, never null, otherwise. `result` and `outcome` are unchanged. 2026-10-11 (#488, additive): optional `fields` and `max_items` make the returned `result` smaller without changing the charge or the stored run. `fields` is a comma-separated list of dotted paths of `result` to keep (arrays are walked element by element); `max_items` keeps at most that many items of every array. A trimmed view carries `trimmed` { truncated, fields?, max_items?, arrays: [{ path, kept, total }] } next to `result`. A `fields` path that matches nothing in this run's result, or a bad value, is a 400 validation_error. Neither parameter: the answer is exactly what it was.","parameters":[{"name":"fields","in":"query","required":false,"description":"Comma-separated dotted paths of `result` to keep, e.g. data.name,data.url","schema":{"type":"string"}},{"name":"max_items","in":"query","required":false,"description":"Keep at most this many items of every array in `result` (1 to 10000)","schema":{"type":"integer","minimum":1,"maximum":10000}}],"operationId":"getRun"}},"/v1/runs/{runId}/cancel":{"post":{"summary":"Cancel a run","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"401":{"description":"unauthorized: a valid bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limit_exceeded: wait Retry-After seconds and send the same request again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before the next request fits the bucket","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Bucket size (legacy header, kept)","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the bucket (legacy header, kept)","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";q=<bucket size>;w=<seconds an empty bucket takes to refill>","schema":{"type":"string"}},"RateLimit":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";r=<remaining>;t=<seconds until the bucket is full>","schema":{"type":"string"}}}},"500":{"description":"internal_error: an unexpected failure; the message is masked, quote requestId when reporting it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"cancelRun","description":"Cancel a run that has not finished. A finished run is answered as it is."}},"/v1/runs/{runId}/attempts":{"get":{"summary":"Inspect durable attempts and receipts","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["attempts","receipts"],"properties":{"attempts":{"type":"array","items":{"type":"object","required":["attemptId","runId","ordinal","endpointId","providerId","status","providerResponseStatus"],"properties":{"attemptId":{"type":"string"},"runId":{"type":"string"},"workspaceId":{"type":"string"},"ordinal":{"type":"integer"},"endpointId":{"type":"string"},"providerId":{"type":"string"},"operationId":{"type":"string"},"operationVersion":{"type":"string"},"executorKind":{"type":"string"},"status":{"enum":["prepared","running","succeeded","provider_error","cancelled","reconciliation_pending"]},"providerResponseStatus":{"type":"string"},"preparedAt":{"type":"string"},"startedAt":{"type":["string","null"]},"completedAt":{"type":["string","null"]},"errorClass":{"type":["string","null"]},"retryOfAttemptId":{"type":["string","null"]},"reconciliationStatus":{"enum":["not_required","pending","resolved"]},"outcome":{"type":"string"}}}},"receipts":{"type":"array","items":{"type":"object","required":["receiptId","attemptId","runId","providerId","settlement"],"properties":{"receiptId":{"type":"string"},"attemptId":{"type":"string"},"runId":{"type":"string"},"providerId":{"type":"string"},"operationId":{"type":"string"},"providerRequestId":{"type":["string","null"]},"providerResponseStatus":{"type":"string"},"customerCharge":{"type":["number","null"]},"settlement":{"enum":["charged","released","retry_scheduled","reconciliation_pending"]},"ledgerEntryRefs":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"quoteId":{"type":["string","null"]}}}}}}}}},"401":{"description":"unauthorized: a valid bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limit_exceeded: wait Retry-After seconds and send the same request again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before the next request fits the bucket","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Bucket size (legacy header, kept)","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the bucket (legacy header, kept)","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";q=<bucket size>;w=<seconds an empty bucket takes to refill>","schema":{"type":"string"}},"RateLimit":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";r=<remaining>;t=<seconds until the bucket is full>","schema":{"type":"string"}}}},"500":{"description":"internal_error: an unexpected failure; the message is masked, quote requestId when reporting it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"listRunAttempts","description":"The durable provider attempts of one run and their receipts, for debugging a fallback walk."}},"/v1/balance":{"get":{"summary":"Get workspace balance. topUpLink includes purchase minimum, dashboard and any pending checkout. Compare funds with each run estimate; the purchase minimum is not a wallet threshold. Reading balance never creates checkout","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["workspaceId","currency","available","reserved","availableMicros","reservedMicros","holds","topUp","topUpLink"],"properties":{"workspaceId":{"type":"string"},"currency":{"const":"USD"},"available":{"type":"number","description":"USD"},"reserved":{"type":"number","description":"USD held by runs in flight"},"availableMicros":{"type":"integer"},"reservedMicros":{"type":"integer"},"recentSpendMicros":{"type":"integer"},"trialCreditMicros":{"type":"integer"},"topUpUrl":{"type":["string","null"]},"holds":{"type":"array","items":{"type":"object","properties":{"reservationId":{"type":"string"},"runId":{"type":["string","null"]},"amountMicros":{"type":"integer"},"createdAt":{"type":"string"}}}},"topUp":{"type":"object","required":["route","available"],"properties":{"route":{"type":"string"},"available":{"type":"boolean"},"reason":{"type":"string"},"currency":{"type":"string"},"minMicros":{"type":"integer"},"maxMicros":{"type":"integer"}}},"topUpLink":{"type":"object","required":["minimumUsd","suggestedUsd","checkoutUrl","dashboardUrl","message"],"properties":{"minimumUsd":{"type":"number"},"suggestedUsd":{"type":"number"},"checkoutUrl":{"type":["string","null"]},"dashboardUrl":{"type":"string"},"message":{"type":"string"},"reason":{"type":"string"}}}}}}}},"401":{"description":"unauthorized: a valid bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limit_exceeded: wait Retry-After seconds and send the same request again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before the next request fits the bucket","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Bucket size (legacy header, kept)","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the bucket (legacy header, kept)","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";q=<bucket size>;w=<seconds an empty bucket takes to refill>","schema":{"type":"string"}},"RateLimit":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";r=<remaining>;t=<seconds until the bucket is full>","schema":{"type":"string"}}}},"500":{"description":"internal_error: an unexpected failure; the message is masked, quote requestId when reporting it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"getBalance","description":"Workspace credit, holds and the top-up link. Reading the balance never creates a checkout."}},"/v1/top-ups":{"get":{"summary":"List prepaid top-ups","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["topUps"],"properties":{"topUps":{"type":"array","items":{"type":"object","required":["topUpId","workspaceId","amountMicros","currency","status","processor","checkoutSessionId","checkoutUrl","createdAt","updatedAt"],"properties":{"topUpId":{"type":"string"},"workspaceId":{"type":"string"},"amountMicros":{"type":"integer"},"currency":{"type":"string"},"status":{"enum":["awaiting_payment_processor","awaiting_payment","paid","expired","failed"]},"processor":{"enum":["not_configured","stripe"]},"checkoutSessionId":{"type":["string","null"]},"checkoutUrl":{"type":["string","null"],"description":"Open it to pay"},"paidByEventId":{"type":["string","null"]},"trigger":{"enum":["manual","auto"]},"paymentIntentId":{"type":["string","null"]},"autoTopUpDay":{"type":["string","null"]},"autoTopUpSequence":{"type":["integer","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}}}}}}},"401":{"description":"unauthorized: a valid bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limit_exceeded: wait Retry-After seconds and send the same request again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before the next request fits the bucket","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Bucket size (legacy header, kept)","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the bucket (legacy header, kept)","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";q=<bucket size>;w=<seconds an empty bucket takes to refill>","schema":{"type":"string"}},"RateLimit":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";r=<remaining>;t=<seconds until the bucket is full>","schema":{"type":"string"}}}},"500":{"description":"internal_error: an unexpected failure; the message is masked, quote requestId when reporting it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"listTopUps","description":"Prepaid top-ups of this workspace and their state."},"post":{"summary":"Request a prepaid top-up (creates a Stripe Checkout Session when Stripe is configured)","responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["topUpId","workspaceId","amountMicros","currency","status","processor","checkoutSessionId","checkoutUrl","createdAt","updatedAt"],"properties":{"topUpId":{"type":"string"},"workspaceId":{"type":"string"},"amountMicros":{"type":"integer"},"currency":{"type":"string"},"status":{"enum":["awaiting_payment_processor","awaiting_payment","paid","expired","failed"]},"processor":{"enum":["not_configured","stripe"]},"checkoutSessionId":{"type":["string","null"]},"checkoutUrl":{"type":["string","null"],"description":"Open it to pay"},"paidByEventId":{"type":["string","null"]},"trigger":{"enum":["manual","auto"]},"paymentIntentId":{"type":["string","null"]},"autoTopUpDay":{"type":["string","null"]},"autoTopUpSequence":{"type":["integer","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}}}},"401":{"description":"unauthorized: a valid bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limit_exceeded: wait Retry-After seconds and send the same request again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before the next request fits the bucket","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Bucket size (legacy header, kept)","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the bucket (legacy header, kept)","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";q=<bucket size>;w=<seconds an empty bucket takes to refill>","schema":{"type":"string"}},"RateLimit":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";r=<remaining>;t=<seconds until the bucket is full>","schema":{"type":"string"}}}},"500":{"description":"internal_error: an unexpected failure; the message is masked, quote requestId when reporting it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"createTopUp","description":"Request a prepaid top-up. Answers a Stripe Checkout link to pay when Stripe is configured."}},"/v1/connections":{"get":{"summary":"List connection metadata","responses":{"200":{"description":"Tenant connection metadata","content":{"application/json":{"schema":{"type":"object","required":["connections"],"properties":{"connections":{"type":"array","items":{"type":"object","required":["id","providerId","label","status","auth","scopes","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"providerId":{"type":"string"},"label":{"type":"string"},"status":{"type":"string"},"auth":{"type":"object","required":["kind"],"properties":{"kind":{"type":"string"}},"description":"Non-secret auth metadata, discriminated by kind; never the secret"},"scopes":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"lastProbe":{"type":["object","null"]},"cooldownUntil":{"type":["string","null"]},"credentialExpiresAt":{"type":["string","null"]},"pendingCredentialRoles":{"type":"array","items":{"type":"string"}},"consent":{"type":"object","properties":{"expiresAt":{"type":["string","null"]},"warning":{"enum":["expiring_soon","expired",null]}}},"testState":{"enum":["not_tested","verified"]},"probeConfigured":{"type":"boolean"},"latestTestReceipt":{"type":["object","null"]}}}}}}}}},"403":{"description":"connections:read scope required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"listConnections","description":"This workspace's provider connections (your own keys or OAuth grants), metadata only. Secrets are never returned."},"post":{"summary":"Register a write-only API credential","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterConnection"}}}},"responses":{"201":{"description":"Connection metadata; secrets and internal references are excluded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Connection"}}}},"403":{"description":"connections:write scope required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Connection already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"createConnection","description":"Register a write-only provider credential. The secret is stored in the vault and never returned."}},"/v1/public-catalog":{"get":{"security":[],"summary":"Search stable redacted public catalog pages by text, capability, category, or provider","description":"Publicly browsable without a bearer token; the catalog is not tenant-scoped.","parameters":[{"name":"text","in":"query","schema":{"type":"string","minLength":1,"maxLength":200},"description":"At most 800 UTF-8 bytes; control characters rejected"},{"name":"q","in":"query","schema":{"type":"string","minLength":1,"maxLength":200},"description":"Alias for text; cannot be combined with text"},{"name":"capability","in":"query","schema":{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"}},{"name":"category","in":"query","schema":{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"}},{"name":"provider","in":"query","schema":{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"}},{"name":"operationId","in":"query","schema":{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string","minLength":1,"maxLength":4096}},{"name":"signals","in":"query","schema":{"enum":["1"]},"description":"1 also returns unsuppliedJobs and warnings when no public endpoint does the query's job; without it that page is items: [] with the three base keys"}],"responses":{"200":{"description":"Stable public catalog page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogPage"}}}},"400":{"description":"Invalid, repeated, or malformed query/cursor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Only returned for a malformed request; no bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Catalog read scope required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"catalog_cursor_stale: cursor no longer matches the query or catalog snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"listPublicCatalog"}},"/v1/public-catalog/{catalogItemId}":{"get":{"security":[],"summary":"Inspect one public published catalog item; hidden and missing ids share 404","description":"Publicly browsable without a bearer token; the catalog is not tenant-scoped.","parameters":[{"name":"catalogItemId","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"}}],"responses":{"200":{"description":"Public catalog item","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogItem"}}}},"401":{"description":"Only returned for a malformed request; no bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Catalog read scope required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Catalog item not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"getPublicCatalogItem"}},"/v1/public-catalog/compare":{"post":{"security":[],"summary":"Compare 2 to 20 explicit public catalog items without inferring missing price semantics","description":"Publicly browsable without a bearer token; the catalog is not tenant-scoped.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["catalogItemIds"],"properties":{"catalogItemIds":{"type":"array","minItems":2,"maxItems":20,"uniqueItems":true,"items":{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"}}}}}}},"responses":{"200":{"description":"Conservative catalog comparison","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCatalogComparison"}}}},"400":{"description":"Invalid selection","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Only returned for a malformed request; no bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Catalog read scope required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"One or more catalog items not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"comparePublicCatalogItems"}},"/v1/session-context":{"get":{"summary":"Get bounded authenticated local session context","parameters":[{"name":"include","in":"query","required":false,"description":"expiresAt adds the token's own expiry to the response; organizationName adds the organization's display name. Comma-separated or repeated.","schema":{"type":"string","examples":["expiresAt","expiresAt,organizationName"]}}],"description":"Returns only the server-derived local organization, authentication class, canonical granted scopes, and local mode. It never returns tokens, token hashes, principal identifiers, vault references, or session identifiers.","responses":{"200":{"description":"Authenticated local session context","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionContext"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"local-product:read scope required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Session context unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"getSessionContext"}},"/v1/whoami":{"get":{"summary":"Current principal's membership, organization, tool grants and machine sessions","responses":{"200":{"description":"Organization, membership, active tool grants and active machine sessions; never includes a tokenHash","content":{"application/json":{"schema":{"type":"object","required":["organization","membership","toolGrants","machineSessions"],"properties":{"organization":{"type":"object","required":["organizationId","slug","displayName","status"],"properties":{"organizationId":{"type":"string"},"slug":{"type":"string"},"displayName":{"type":"string"},"status":{"enum":["active","suspended","deleted"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}},"membership":{"type":"object","required":["membershipId","organizationId","principalId","role","status"],"properties":{"membershipId":{"type":"string"},"organizationId":{"type":"string"},"principalId":{"type":"string"},"role":{"type":"string"},"status":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}},"toolGrants":{"type":"array","items":{"type":"object","properties":{"grantId":{"type":"string"},"toolId":{"type":"string"},"permissions":{"type":"array","items":{"enum":["inspect","execute","manage"]}},"expiresAt":{"type":["string","null"]},"revokedAt":{"type":["string","null"]}}}},"machineSessions":{"type":"array","description":"Never includes a token or token hash","items":{"type":"object","properties":{"sessionId":{"type":"string"},"label":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"expiresAt":{"type":"string"},"lastUsedAt":{"type":["string","null"]},"revokedAt":{"type":["string","null"]}}}}}}}}},"403":{"description":"organizations:read scope required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No membership in the token's organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Control plane unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"getWhoami","description":"The caller's organization, membership, tool grants and machine sessions. Never includes a token or token hash."}},"/v1/catalog/overview":{"get":{"security":[],"summary":"What the catalog covers: categories > platforms > jobs with provider, endpoint and runnable counts","description":"Publicly readable without a bearer token; the same answer for every caller, rebuilt only when the catalog revision (or a platform key or fee) changes. Counts the rows the live public catalog lists (GET /v1/public-catalog when it serves the live catalog): the same row rules and public record checks (hidden slugs, prohibited, mock, unpriced, inactive and disabled rows, and records the public schema refuses, are left out). A category is the vocabulary category of the job's platform, `other` when the platform is not in the vocabulary. Every level (category, platform, job) carries providerCount (distinct providers), endpointCount, runnableCount (runnable without your own key: keyless, or a platform key exists), cheapestPerCall and cheapestPerResult (lowest prices, the price you pay, null when nothing is priced that way; never compared with each other). The default answer is depth summary (totals plus one entry per category, a few KB); depth=full is the whole document (about 490 KB). category or platform narrows to one branch (default depth platforms; depth=jobs lists its jobs) and then answers filter instead of totals. topic answers the matching jobs, at most 25. Each view has its own ETag; revalidate with If-None-Match.","parameters":[{"name":"depth","in":"query","required":false,"schema":{"enum":["summary","platforms","jobs","full"]},"description":"summary (default): totals and per category counts. platforms: adds each category's platforms. jobs: adds each platform's jobs (a tree). full: each category's platforms[] and flat jobs[] with job.platform. Default platforms when category or platform is given; pass jobs to list the branch jobs. Not allowed with topic."},{"name":"category","in":"query","required":false,"schema":{"type":"string","maxLength":200},"description":"A category id: answers only that category. Unknown: 404 unknown_category."},{"name":"platform","in":"query","required":false,"schema":{"type":"string","maxLength":200},"description":"A platform id: answers the category holding it with only that platform. Unknown (or not in the given category): 404 unknown_platform."},{"name":"topic","in":"query","required":false,"schema":{"type":"string","maxLength":200},"description":"Words such as email or phone: answers the jobs whose id, title, platform or category match (the job-first search matcher), best first, at most 25, with truncated. Combines with category and platform."},{"name":"If-None-Match","in":"header","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Catalog overview view: a depth view, or a topic view when topic is given","headers":{"ETag":{"schema":{"type":"string"},"description":"W/\"rev-<revision>-<digest of this view>\""}},"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/CatalogOverview"},{"$ref":"#/components/schemas/CatalogOverviewTopic"}]}}}},"304":{"description":"View unchanged since If-None-Match"},"400":{"description":"validation_error: error.field names the argument (depth, category, platform or topic) and error.message says what to send","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"unknown_category (error.categories lists the ids) or unknown_platform; error.field names the argument","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"catalog_loading: no catalog snapshot is loaded yet; retry after retry-after seconds. production_runtime_unavailable: this deployment serves no v2 catalog","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"getCatalogOverview"}},"/v1/ledger":{"get":{"summary":"List ledger entries","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["entries","nextCursor"],"properties":{"entries":{"type":"array","items":{"type":"object","required":["entryId","workspaceId","type","amount","amountMicros","createdAt"],"properties":{"entryId":{"type":"string"},"workspaceId":{"type":"string"},"type":{"enum":["top_up","trial_credit","reservation","release","charge","refund"]},"amount":{"type":"number"},"amountMicros":{"type":"integer"},"runId":{"type":["string","null"]},"reservationId":{"type":["string","null"]},"createdAt":{"type":"string"},"note":{"type":"string"},"sourceEntryId":{"type":["string","null"]}}}},"nextCursor":{"type":["string","null"]}}}}}},"401":{"description":"unauthorized: a valid bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limit_exceeded: wait Retry-After seconds and send the same request again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before the next request fits the bucket","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Bucket size (legacy header, kept)","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the bucket (legacy header, kept)","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";q=<bucket size>;w=<seconds an empty bucket takes to refill>","schema":{"type":"string"}},"RateLimit":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";r=<remaining>;t=<seconds until the bucket is full>","schema":{"type":"string"}}}},"500":{"description":"internal_error: an unexpected failure; the message is masked, quote requestId when reporting it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"listLedgerEntries","description":"Ledger entries of this workspace: holds, settlements, releases and top-ups, newest first."}},"/v1/capability-requests":{"get":{"summary":"List tenant capability requests","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","required":["requestId","title","description","desiredInputs","desiredOutputs","status","createdAt","updatedAt"],"properties":{"requestId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"desiredInputs":{"type":"array","items":{"type":"string"}},"desiredOutputs":{"type":"array","items":{"type":"string"}},"status":{"enum":["open","under_review","resolved","closed"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}}}}},"401":{"description":"unauthorized: a valid bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limit_exceeded: wait Retry-After seconds and send the same request again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before the next request fits the bucket","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Bucket size (legacy header, kept)","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the bucket (legacy header, kept)","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";q=<bucket size>;w=<seconds an empty bucket takes to refill>","schema":{"type":"string"}},"RateLimit":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";r=<remaining>;t=<seconds until the bucket is full>","schema":{"type":"string"}}}},"500":{"description":"internal_error: an unexpected failure; the message is masked, quote requestId when reporting it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"listCapabilityRequests","description":"Capability requests this workspace has sent: jobs or providers it asked looot to add."},"post":{"summary":"Create an idempotent tenant capability request","responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["requestId","title","description","desiredInputs","desiredOutputs","status","createdAt","updatedAt"],"properties":{"requestId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"desiredInputs":{"type":"array","items":{"type":"string"}},"desiredOutputs":{"type":"array","items":{"type":"string"}},"status":{"enum":["open","under_review","resolved","closed"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}}}},"401":{"description":"unauthorized: a valid bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limit_exceeded: wait Retry-After seconds and send the same request again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before the next request fits the bucket","schema":{"type":"integer","minimum":1}},"X-RateLimit-Limit":{"description":"Bucket size (legacy header, kept)","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the bucket (legacy header, kept)","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";q=<bucket size>;w=<seconds an empty bucket takes to refill>","schema":{"type":"string"}},"RateLimit":{"description":"IETF draft-ietf-httpapi-ratelimit-headers: \"<policy>\";r=<remaining>;t=<seconds until the bucket is full>","schema":{"type":"string"}}}},"500":{"description":"internal_error: an unexpected failure; the message is masked, quote requestId when reporting it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"createCapabilityRequest","description":"Ask looot to add a job or provider the catalog does not cover. Idempotent on its key."}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"CatalogOverview":{"type":"object","additionalProperties":false,"required":["revision","builtAt","depth","categories"],"properties":{"revision":{"type":"string"},"builtAt":{"type":"string","format":"date-time"},"depth":{"enum":["summary","platforms","jobs","full"]},"filter":{"type":"object","additionalProperties":false,"description":"Present only on a narrowed view (category or platform given); such a view has no totals","properties":{"category":{"type":"string"},"platform":{"type":"string"}}},"totals":{"type":"object","additionalProperties":false,"description":"Whole catalog; only on a view that is not narrowed","required":["categories","platforms","jobs","providers","endpoints","runnableEndpoints"],"properties":{"categories":{"type":"integer"},"platforms":{"type":"integer"},"jobs":{"type":"integer"},"providers":{"type":"integer"},"endpoints":{"type":"integer"},"runnableEndpoints":{"type":"integer"}}},"categories":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","title","platformCount","jobCount","providerCount","endpointCount","runnableCount","cheapestPerCall","cheapestPerResult"],"properties":{"id":{"type":"string"},"title":{"type":"string"},"platformCount":{"type":"integer"},"jobCount":{"type":"integer"},"providerCount":{"type":"integer","description":"Distinct providers with at least one listed endpoint at this level"},"endpointCount":{"type":"integer"},"runnableCount":{"type":"integer","description":"Endpoints runnable without your own key (keyless, or a platform key exists)"},"cheapestPerCall":{"type":["number","null"],"description":"Lowest per-call price in dollars at this level (the price you pay); null when nothing is priced per call"},"cheapestPerResult":{"type":["number","null"],"description":"Lowest per-result price in dollars at this level (the price you pay); null when nothing is priced per result"},"platforms":{"type":"array","description":"Depth platforms, jobs and full, and any view narrowed by platform","items":{"type":"object","additionalProperties":false,"required":["id","title","jobCount","providerCount","endpointCount","runnableCount","cheapestPerCall","cheapestPerResult"],"properties":{"id":{"type":"string"},"title":{"type":"string"},"jobCount":{"type":"integer"},"providerCount":{"type":"integer","description":"Distinct providers with at least one listed endpoint at this level"},"endpointCount":{"type":"integer"},"runnableCount":{"type":"integer","description":"Endpoints runnable without your own key (keyless, or a platform key exists)"},"cheapestPerCall":{"type":["number","null"],"description":"Lowest per-call price in dollars at this level (the price you pay); null when nothing is priced per call"},"cheapestPerResult":{"type":["number","null"],"description":"Lowest per-result price in dollars at this level (the price you pay); null when nothing is priced per result"},"jobs":{"type":"array","description":"Depth jobs only: this platform's jobs","items":{"type":"object","additionalProperties":false,"required":["id","title","providerCount","endpointCount","runnableCount","cheapestPerCall","cheapestPerResult"],"properties":{"id":{"type":"string"},"title":{"type":"string"},"providerCount":{"type":"integer","description":"Distinct providers with at least one listed endpoint at this level"},"endpointCount":{"type":"integer"},"runnableCount":{"type":"integer","description":"Endpoints runnable without your own key (keyless, or a platform key exists)"},"cheapestPerCall":{"type":["number","null"],"description":"Lowest per-call price in dollars at this level (the price you pay); null when nothing is priced per call"},"cheapestPerResult":{"type":["number","null"],"description":"Lowest per-result price in dollars at this level (the price you pay); null when nothing is priced per result"}}}}}}},"jobs":{"type":"array","description":"Depth full only: the category's jobs, each naming its platform","items":{"type":"object","additionalProperties":false,"required":["id","title","platform","providerCount","endpointCount","runnableCount","cheapestPerCall","cheapestPerResult"],"properties":{"id":{"type":"string"},"title":{"type":"string"},"platform":{"type":"string"},"providerCount":{"type":"integer","description":"Distinct providers with at least one listed endpoint at this level"},"endpointCount":{"type":"integer"},"runnableCount":{"type":"integer","description":"Endpoints runnable without your own key (keyless, or a platform key exists)"},"cheapestPerCall":{"type":["number","null"],"description":"Lowest per-call price in dollars at this level (the price you pay); null when nothing is priced per call"},"cheapestPerResult":{"type":["number","null"],"description":"Lowest per-result price in dollars at this level (the price you pay); null when nothing is priced per result"}}}}}}}}},"CatalogOverviewTopic":{"type":"object","additionalProperties":false,"required":["revision","builtAt","topic","matchCount","truncated","jobs"],"properties":{"revision":{"type":"string"},"builtAt":{"type":"string","format":"date-time"},"topic":{"type":"string","description":"The topic as matched: lowercased, punctuation folded to spaces"},"filter":{"type":"object","additionalProperties":false,"description":"Present only on a narrowed view (category or platform given); such a view has no totals","properties":{"category":{"type":"string"},"platform":{"type":"string"}}},"matchCount":{"type":"integer","description":"Jobs that match before the cap"},"truncated":{"type":"boolean","description":"True when matchCount is over the 25 jobs answered"},"jobs":{"type":"array","maxItems":25,"items":{"type":"object","additionalProperties":false,"required":["id","title","providerCount","endpointCount","runnableCount","cheapestPerCall","cheapestPerResult","category","platform"],"properties":{"id":{"type":"string"},"title":{"type":"string"},"providerCount":{"type":"integer","description":"Distinct providers with at least one listed endpoint at this level"},"endpointCount":{"type":"integer"},"runnableCount":{"type":"integer","description":"Endpoints runnable without your own key (keyless, or a platform key exists)"},"cheapestPerCall":{"type":["number","null"],"description":"Lowest per-call price in dollars at this level (the price you pay); null when nothing is priced per call"},"cheapestPerResult":{"type":["number","null"],"description":"Lowest per-result price in dollars at this level (the price you pay); null when nothing is priced per result"},"category":{"type":"string"},"platform":{"type":"string"}}}}}},"Connection":{"type":"object","additionalProperties":false,"required":["id","providerId","label","status","auth","scopes","lastProbe","cooldownUntil","credentialExpiresAt","consent","pendingCredentialRoles","createdAt","updatedAt","testState"],"properties":{"id":{"type":"string"},"providerId":{"type":"string"},"label":{"type":"string"},"status":{"enum":["draft","authorization_pending","connected","degraded","expired","action_required","revoked"]},"auth":{"type":"object","additionalProperties":false,"required":["kind"],"properties":{"kind":{"enum":["none","api_key","oauth","service_account","credential_file","signed_request","cli_auth"]},"placement":{"enum":["header","query"]},"name":{"type":"string"},"authorizationUrl":{"type":"string"},"tokenUrl":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"tokenPlacement":{"enum":["header","query"]},"algorithm":{"const":"hmac-sha256"},"signedHeaders":{"type":"array","items":{"type":"string"}}}},"scopes":{"type":"array","items":{"type":"string"},"description":"Granted scopes, populated after oauth callback or a probe that reports scopes"},"lastProbe":{"anyOf":[{"$ref":"#/components/schemas/ConnectionHealthReceipt"},{"type":"null"}]},"cooldownUntil":{"type":["string","null"],"format":"date-time"},"credentialExpiresAt":{"type":["string","null"],"format":"date-time"},"consent":{"type":"object","additionalProperties":false,"required":["expiresAt","warning"],"properties":{"expiresAt":{"type":["string","null"],"format":"date-time"},"warning":{"enum":["expiring_soon","expired",null]}}},"pendingCredentialRoles":{"type":"array","items":{"type":"string"},"description":"Declared secondary credential roles not yet supplied; non-empty implies status action_required"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"testState":{"enum":["not_tested","verified"],"description":"verified requires at least one persisted fixture_tested receipt; never set from CRUD alone"},"probeConfigured":{"type":"boolean","description":"true when POST /v1/connections/{connectionId}/probe has a live health check to run; false for a pasted api_key with no probe (the probe then answers 400 validation_error with reason connection_probe_not_configured)"},"latestTestReceipt":{"anyOf":[{"$ref":"#/components/schemas/ConnectionFixtureReceipt"},{"type":"null"}],"description":"Present only in the GET /v1/connections list response (absent, not null, on register/rotate/revoke/etc. responses); the same object GET /v1/connections/{connectionId}/test-receipts returns as `latest`"}}},"ConnectionFixtureReceipt":{"type":"object","additionalProperties":false,"required":["receiptId","connectionId","verification","providerCalled","credentialState","evidence","testedAt"],"properties":{"receiptId":{"type":"string","pattern":"^cfr_[a-f0-9]{32}$"},"connectionId":{"type":"string","pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"verification":{"const":"fixture_tested"},"providerCalled":{"type":"boolean"},"credentialState":{"const":"available"},"evidence":{"const":"local_fixture_credential_access"},"testedAt":{"type":"string","format":"date-time"}}},"ConnectionHealthReceipt":{"type":"object","additionalProperties":false,"required":["receiptId","connectionId","providerId","outcome","status","identity","scopes","resources","providerRequestId","remediation","checkedAt"],"properties":{"receiptId":{"type":"string","pattern":"^chr_[a-f0-9]{32}$"},"connectionId":{"type":"string"},"providerId":{"type":"string"},"outcome":{"enum":["healthy","invalid_credentials","insufficient_scope","unavailable","rate_limited","missing_resource"]},"status":{"type":["integer","null"]},"identity":{"type":["string","null"]},"scopes":{"type":"array","items":{"type":"string"}},"resources":{"type":"array","items":{"type":"string"},"description":"Accessible provider resource ids discovered by this probe (CA-CONN-03)"},"providerRequestId":{"type":["string","null"]},"remediation":{"type":["string","null"],"description":"Safe human-readable next step; never credential material"},"checkedAt":{"type":"string","format":"date-time"}}},"ConnectionProbeDefinition":{"type":"object","additionalProperties":false,"required":["host","method","path","expectedStatuses"],"properties":{"host":{"type":"string"},"method":{"enum":["GET","POST"]},"path":{"type":"string"},"expectedStatuses":{"type":"array","items":{"type":"integer"}},"identityPointer":{"type":"string"},"scopesPointer":{"type":"string"},"resourcesPointer":{"type":"string"}}},"Error":{"type":"object","description":"The looot error envelope that problem() builds (src/http/problem.ts), sent as application/json for every error status. It is not RFC 9457 problem+json. Branch on error.code. Some codes add fields: inside error (for example field and categories on unknown_category) or next to it (for example retryAfterSeconds and limit on a 429).","required":["error"],"properties":{"error":{"type":"object","required":["code","message","requestId"],"properties":{"code":{"type":"string","description":"Stable snake_case error code, for example unauthorized, validation_error, rate_limit_exceeded, internal_error"},"message":{"type":"string","description":"Human-readable explanation; wording may change, the code does not"},"requestId":{"type":"string","description":"Same value as the x-request-id response header"}}},"retryAfterSeconds":{"type":"integer","minimum":0,"description":"On retryable refusals: seconds to wait, the same value as Retry-After"}}},"InspectOutput":{"type":"object","additionalProperties":false,"required":["endpoint","estimatedMaxCost","usageHints"],"properties":{"endpoint":{"type":"object","description":"Exact registered endpoint metadata"},"estimatedMaxCost":{"type":"number","minimum":0,"description":"The most one call can cost through the platform key, fee included: what the run's hold reserves for the dearest value of the priced input field, with no volume input set (see priceRange)"},"priceRange":{"type":"object","additionalProperties":false,"required":["minMicros","maxMicros","feeMicros","scalesWith"],"description":"The price of one call as a range, in micros, fee included. Absent when your own connected key runs it at $0","properties":{"minMicros":{"type":"integer","minimum":0,"description":"The cheapest input"},"maxMicros":{"type":"integer","minimum":0,"description":"The dearest priced-input value, no volume input set; equals estimatedMaxCost"},"feeMicros":{"type":"integer","minimum":0,"description":"looot's flat fee per call, included in min and max"},"byInput":{"type":"object","additionalProperties":false,"required":["field","perResult","ratesMicros"],"description":"Present when the price depends on one input field: the rate per value","properties":{"field":{"type":"string"},"perResult":{"type":"boolean","description":"true: rates are per unit (result, second, token), the fee is added once per call; false: rates are per call, fee included"},"ratesMicros":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}}},"scalesWith":{"type":"array","items":{"type":"string"},"description":"Volume inputs (JSON pointers) that raise the cost above maxMicros when set higher, e.g. /max_tokens or /input/duration"}}},"inputSchema":{"type":["object","null"],"description":"Draft 2020-12 input schema resolved from fixture, activation bundle, or direct registration; null when the endpoint declares none"},"requestBinding":{"type":["object","null"],"description":"How validated input fields become the HTTP request (path/query/header/body); null for a fixture or bundle-published endpoint that declares none"},"uiSchema":{"type":["object","null"],"description":"Presentation hints for a generated form; never validation"},"outputFormat":{"type":"object","additionalProperties":false,"required":["schema","summary","provenance","note"],"description":"The endpoint's stored output format, present only when one is stored. Check provenance.verified before relying on it: false means an expected shape not yet checked against real answers","properties":{"schema":{"type":"object","description":"Draft 2020-12 output schema, structure only; its $comment says where it came from"},"summary":{"type":"string","description":"One-line summary of the schema"},"provenance":{"type":"object","additionalProperties":false,"required":["source","validatedAnswers","checkedAnswers","verified"],"properties":{"source":{"enum":["own-answers","treg-shape","both","unknown"]},"validatedAnswers":{"type":"integer","minimum":0,"description":"Real saved answers that matched the schema"},"checkedAnswers":{"type":"integer","minimum":0,"description":"Real saved answers the schema was checked against"},"verified":{"type":"boolean","description":"True only when at least one real answer was checked and every one matched"}}},"note":{"type":"string","description":"One-line label, e.g. \"validated on 12 real answers\" or \"expected shape, not yet checked against real answers\""}}},"usageHints":{"type":"object","additionalProperties":false,"required":["endpointId","operationVersion","contractDigest","authentication","requiredInputFields","outputSchema","examples"],"properties":{"endpointId":{"type":"string"},"operationVersion":{"type":"string"},"contractDigest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"authentication":{"type":"object","description":"Bearer placeholder only; never contains a credential"},"requiredInputFields":{"type":"array","items":{"type":"string"}},"outputSchema":{"type":"object","description":"Pinned Draft 2020-12 output schema"},"examples":{"type":"object","description":"Equivalent REST, MCP, and CLI requests using placeholders only"}}}}},"PublicCatalogComparison":{"type":"object","additionalProperties":false,"required":["items","priceComparison","comparisonDigest"],"properties":{"items":{"type":"array","minItems":2,"maxItems":20,"items":{"$ref":"#/components/schemas/PublicCatalogItem"}},"priceComparison":{"oneOf":[{"type":"object","additionalProperties":false,"required":["state","currency","unit","amounts","lowestAmountMicros","lowestCatalogItemIds"],"properties":{"state":{"const":"comparable"},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"unit":{"type":"string","minLength":1,"maxLength":80},"amounts":{"type":"array","minItems":2,"maxItems":20,"items":{"type":"object","additionalProperties":false,"required":["catalogItemId","amountMicros"],"properties":{"catalogItemId":{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"},"amountMicros":{"type":"integer","minimum":0,"maximum":9007199254740991}}}},"lowestAmountMicros":{"type":"integer","minimum":0,"maximum":9007199254740991},"lowestCatalogItemIds":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"}}}},{"type":"object","additionalProperties":false,"required":["state","reason"],"properties":{"state":{"const":"not_comparable"},"reason":{"enum":["price_state_unknown_or_uncomputable","capability_or_contract_mismatch","price_semantics_unverified","currency_or_unit_mismatch"]}}}]},"comparisonDigest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"}}},"PublicCatalogItem":{"type":"object","additionalProperties":false,"required":["catalogItemId","revision","providerId","operationId","title","description","categories","capabilities","inputSchemaDigest","outputSchemaDigest","method","pathTemplate","parameters","verification","references","price","publishedAt","itemDigest","provenanceTier"],"properties":{"catalogItemId":{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"},"revision":{"type":"integer","minimum":1,"maximum":9007199254740991},"providerId":{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"},"operationId":{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"},"title":{"type":"string","minLength":1,"maxLength":160},"description":{"type":"string","minLength":1,"maxLength":2000},"categories":{"type":"array","minItems":1,"maxItems":30,"items":{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"}},"capabilities":{"type":"array","maxItems":30,"items":{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"}},"inputSchemaDigest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"outputSchemaDigest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"method":{"type":["string","null"],"enum":["GET","POST","PUT","PATCH","DELETE",null]},"pathTemplate":{"type":["string","null"],"minLength":1,"maxLength":1024},"parameters":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["name","location","required"],"properties":{"name":{"type":"string","minLength":1,"maxLength":120},"location":{"enum":["query","path","header","body"]},"required":{"type":"boolean"},"description":{"type":"string","minLength":1,"maxLength":500},"schemaDigest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"}}}},"verification":{"type":"object","additionalProperties":false,"required":["state","verifiedAt","responseCapture"],"properties":{"state":{"enum":["unverified","fixture_verified","authenticated_verified","stale"]},"verifiedAt":{"type":["string","null"],"format":"date-time"},"responseCapture":{"type":"object","additionalProperties":false,"required":["available","digest"],"properties":{"available":{"type":"boolean"},"digest":{"type":["string","null"],"pattern":"^sha256:[a-f0-9]{64}$"}}}}},"references":{"type":"array","maxItems":20,"items":{"type":"object","additionalProperties":false,"required":["kind","url"],"properties":{"kind":{"enum":["documentation","pricing"]},"url":{"type":"string","format":"uri","maxLength":2048}}}},"price":{"$ref":"#/components/schemas/PublicCatalogPrice"},"publishedAt":{"type":"string","format":"date-time"},"itemDigest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"provenanceTier":{"enum":["official","verified_partner","community","private","unverified"]}}},"PublicCatalogPage":{"type":"object","additionalProperties":false,"required":["items","catalogDigest","nextCursor"],"properties":{"items":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/PublicCatalogItem"}},"catalogDigest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"nextCursor":{"type":["string","null"],"minLength":1,"maxLength":2000},"unsuppliedJobs":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"string","minLength":1,"maxLength":200},"description":"Sent only with signals=1 and together with warnings: best-matching job ids no public endpoint is filed under"},"warnings":{"type":"array","minItems":1,"maxItems":5,"description":"Sent only with signals=1, when no public endpoint does the query's job; items is then empty","items":{"type":"object","additionalProperties":false,"required":["code","jobId","jobTitle","message"],"properties":{"code":{"const":"no_supply_for_job"},"jobId":{"type":"string","minLength":1,"maxLength":200},"jobTitle":{"type":"string","minLength":1,"maxLength":300},"message":{"type":"string","minLength":1,"maxLength":1000}}}}}},"PublicCatalogPrice":{"oneOf":[{"type":"object","additionalProperties":false,"required":["state","amountMicros","currency","unit","effectiveAt"],"properties":{"state":{"const":"known"},"amountMicros":{"type":"integer","minimum":0,"maximum":9007199254740991},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"unit":{"type":"string","minLength":1,"maxLength":80},"effectiveAt":{"type":"string","format":"date-time"},"comparisonBasis":{"type":"object","additionalProperties":false,"required":["canonicalMeter","billingBasis","tier","minimumMicros","rounding"],"properties":{"canonicalMeter":{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"},"billingBasis":{"enum":["per_call","per_result","per_unit"]},"tier":{"type":"string","minLength":1,"maxLength":80},"minimumMicros":{"type":"integer","minimum":0,"maximum":9007199254740991},"rounding":{"enum":["exact","ceil","floor"]}}}}},{"type":"object","additionalProperties":false,"required":["state","reason"],"properties":{"state":{"enum":["unknown","uncomputable"]},"reason":{"type":"string","minLength":1,"maxLength":300}}}]},"RegisterConnection":{"type":"object","description":"One of api_key (default when kind is omitted), oauth, service_account, credential_file, signed_request, or cli_auth, discriminated by kind","additionalProperties":true,"required":["id","providerId","label"],"properties":{"kind":{"enum":["api_key","oauth","service_account","credential_file","signed_request","cli_auth"]},"id":{"type":"string","pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"providerId":{"type":"string","pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"label":{"type":"string"},"placement":{"enum":["header","query"]},"name":{"type":"string"},"format":{"type":"string","description":"e.g. \"Bearer {secret}\""},"secret":{"type":"string","writeOnly":true},"authorizationUrl":{"type":"string","format":"uri"},"tokenUrl":{"type":"string","format":"uri"},"scopes":{"type":"array","items":{"type":"string"}},"tokenPlacement":{"enum":["header","query"]},"clientId":{"type":"string","writeOnly":true},"keyFile":{"type":"string","writeOnly":true},"file":{"type":"string","writeOnly":true},"keyId":{"type":"string"},"algorithm":{"const":"hmac-sha256"},"signedHeaders":{"type":"array","items":{"type":"string"}},"blob":{"type":"string","writeOnly":true},"credentialExpiresAt":{"type":["string","null"],"format":"date-time"},"probe":{"anyOf":[{"$ref":"#/components/schemas/ConnectionProbeDefinition"},{"type":"null"}]},"secondaryCredentialRoles":{"type":"array","items":{"type":"string"},"description":"Secondary credential roles this provider requires beyond the primary auth"}}},"Run":{"type":"object","description":"One run (RunRecord with the customer error view, src/types.ts). Read status and outcome, not the HTTP status. Cost fields are USD; provider cost and fee fields are never sent.","required":["runId","idempotencyKey","endpointId","workspaceId","status","providerResponseStatus","createdAt","startedAt","completedAt","input","result","errorClass","estimatedCost","actualCost","error","outcome"],"properties":{"runId":{"type":"string"},"idempotencyKey":{"type":"string"},"endpointId":{"type":"string"},"workspaceId":{"type":"string"},"status":{"enum":["queued","running","completed","failed","blocked","stopped","reconciliation_pending","pending_provider"]},"providerResponseStatus":{"enum":["ok","provider_error","timeout","not_yet_called"]},"createdAt":{"type":"string"},"startedAt":{"type":["string","null"]},"completedAt":{"type":["string","null"]},"input":{"type":"object"},"result":{"description":"The provider answer; null until the run completes"},"errorClass":{"type":["string","null"]},"estimatedCost":{"type":"number"},"actualCost":{"type":["number","null"],"description":"What the run charged; null while reconciliation is pending"},"reservationId":{"type":["string","null"]},"error":{"type":["object","null"],"description":"Set only on a failed or blocked run (RunErrorView, src/runs-error-view.ts)","required":["code","message","whoseError","retryable"],"properties":{"code":{"type":"string"},"providerStatus":{"type":["integer","null"]},"message":{"type":"string"},"requestId":{"type":["string","null"]},"whoseError":{"enum":["provider","gateway","customer"]},"retryable":{"type":"boolean"},"retryHint":{"type":["string","null"]},"details":{"type":"object"},"providerMessage":{"type":"string"}}},"outcome":{"enum":["hit","weak","miss","error","rejected","skipped","pending"]},"outcomeReason":{"type":["string","null"]},"replayed":{"type":"boolean","description":"true when an earlier run with the same idempotencyKey was answered"},"servedEndpointId":{"type":"string"},"servedProviderId":{"type":["string","null"]},"resultBytes":{"type":"integer"},"resultExpired":{"type":"boolean"},"pricing":{"type":"object","properties":{"source":{"type":"string"},"quoteId":{"type":"string"},"finalChargeMicros":{"type":"integer"},"byok":{"type":"boolean"}}},"estimatedCostMicros":{"type":"integer","description":"GET /v1/runs/{runId} only"},"actualCostMicros":{"type":["integer","null"],"description":"GET /v1/runs/{runId} only"},"reconciliationStatus":{"enum":["none","pending","resolved"],"description":"GET /v1/runs/{runId} only"},"settlement":{"type":"object","description":"GET /v1/runs/{runId} only","properties":{"reservationId":{"type":["string","null"]},"reservedMicros":{"type":"integer"},"chargedMicros":{"type":"integer"},"releasedMicros":{"type":"integer"}}},"normalized":{"type":"object","description":"Only when the gateway has normalized output on and the endpoint has an output map"},"message":{"type":"string","description":"Only on pending_provider"},"reconciliation":{"type":"object","description":"Only on reconciliation_pending"}}},"RunRequest":{"type":"object","additionalProperties":false,"required":["endpointId","input"],"properties":{"endpointId":{"type":"string","minLength":1,"description":"The catalog endpoint id to run"},"input":{"type":"object","description":"Arbitrary key/value input, validated against the endpoint's own input schema"},"idempotencyKey":{"type":"string","minLength":1,"description":"Required, unless supplied instead as the Idempotency-Key request header (either satisfies the requirement; supplying both requires them to match, or the request is a 400). A replay with the same key and the same body returns the original run (replayed:true); the same key with a different body is a 409. Never auto-generated by the gateway -- see the report's decision options for why."},"output":{"type":"object","description":"Optional output selection/mapping pin; same shape as an inspected endpoint's outputMappingPin"},"wait":{"oneOf":[{"type":"boolean"},{"type":"number","minimum":0,"maximum":60}],"description":"Optional alternative to the ?wait= query parameter (the query parameter wins if both are given)"},"fallback":{"description":"Optional. Let the run move to the next provider of the same job when one misses or fails, within ONE hold; only attempts that ran are charged. true takes every default. The run then carries `route` {servedBy, outcome, chargedUsd, capped, attempts[], skipped[], summary}.","oneOf":[{"type":"boolean"},{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean","description":"false turns it off (the same as omitting fallback)"},"maxAttempts":{"type":"integer","minimum":1,"maximum":10,"description":"Dispatched attempts, default 3"},"maxCostUsd":{"type":"number","exclusiveMinimum":0,"maximum":100,"description":"The route's cap; default the sum of the first maxAttempts prices; can only lower it"},"prefer":{"enum":["cheapest","reliable","fastest","balanced"],"description":"Order of the job's other providers, default balanced"},"exclude":{"type":"array","maxItems":50,"items":{"type":"string","minLength":1,"maxLength":200},"description":"Endpoint or provider ids never tried"},"stopAtFirstMiss":{"type":"boolean","description":"Stop at the first empty answer, default false"}}}]}}},"SessionContext":{"type":"object","additionalProperties":false,"required":["mode","authenticationClass","organizationId","scopes","deploymentMode","role"],"properties":{"mode":{"const":"local_alpha"},"authenticationClass":{"enum":["local_static_token","machine_session"]},"organizationId":{"oneOf":[{"type":"string","pattern":"^[a-z][a-z0-9_-]{2,127}$"},{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}]},"scopes":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^(?:\\*|[a-z][a-z0-9-]{0,62}(?::(?:\\*|[a-z][a-z0-9-]{0,62}))?)$"}},"deploymentMode":{"description":"Operator-facing deployment mode: fixture_demo/authenticated_sandbox in local_alpha, approved_production in production, degraded whenever live readiness fails regardless of mode.","enum":["fixture_demo","authenticated_sandbox","approved_production","degraded"]},"role":{"description":"The resolved principal's organization role; null for a resolver that never set one.","enum":["owner","admin","member","viewer",null]},"expiresAt":{"description":"Present only for ?include=expiresAt: the presenting token's own expiry (ISO 8601 UTC), or null when it has none.","type":["string","null"],"format":"date-time"},"organizationName":{"description":"Present only for ?include=organizationName: the organization's display name, or null when the gateway could not read one.","type":["string","null"],"minLength":1,"maxLength":120}}}}}}