{"openapi":"3.1.0","info":{"title":"Vindex API","version":"0.2.0","description":"Pre-generation prompt screening for generative-AI platforms. Errors are RFC 7807 `application/problem+json` with a stable `code`. Every `/v1/*` response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`; the limit is the plan's (`GET /v1/plan`). A key reads its own mode's data only: a test key never sees a live decision, review item or usage, and a live key never sees a test one. A 402 (`plan_required`, `subscription_paused`, `subscription_inactive`) carries `upgrade_url`."},"servers":[{"url":"https://api.getvindex.com"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"A Vindex API key: `vx_live_…` or `vx_test_…`. Test-mode keys write `mode: test` decisions and never fire webhooks."}},"schemas":{"CheckResponse":{"type":"object","properties":{"id":{"type":"string","example":"dec_3f2a0c9e8b7d4c6a9f1e2d3c4b5a6978"},"outcome":{"$ref":"#/components/schemas/Outcome"},"tags":{"type":"array","items":{"type":"string"}},"checks":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/CheckScore"}},"policy":{"type":"object","properties":{"id":{"type":["string","null"]},"version":{"type":["integer","null"]}},"required":["id","version"]},"engine_version":{"type":["string","null"],"description":"An opaque id for the screening engine version that decided this.","example":"2026.09"},"latency_ms":{"type":["integer","null"]},"dry_run":{"type":"boolean"},"mode":{"$ref":"#/components/schemas/KeyMode"},"shadow_mode":{"type":"boolean","description":"The tenant is in shadow mode: this decision was logged, but no review item was opened and no webhook sent, so don't enforce it yet. Never true on a block by `minors_sexual`: that line is enforced in shadow mode too."}},"required":["id","outcome","tags","checks","policy","engine_version","latency_ms","dry_run","mode","shadow_mode"]},"Outcome":{"type":"string","enum":["allow","review","block"]},"CheckScore":{"type":"object","properties":{"score":{"type":"number","description":"Routes against the policy's act line."},"review_score":{"type":"number","description":"Routes against the policy's review line."},"fired":{"type":"array","items":{"type":"string"},"description":"Signals that crossed their own line: question ids, `floor:*`, `adult_claim`…"}},"required":["score","review_score","fired"]},"KeyMode":{"type":"string","enum":["live","test"]},"Problem":{"type":"object","properties":{"type":{"type":"string","example":"https://api.getvindex.com/problems/invalid_request"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"code":{"type":"string","description":"Stable machine-readable error code."},"issues":{"type":"array","items":{"type":"string"},"description":"Validation issues, one per problem found."}},"required":["type","title","status"]},"PlanProblem":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"type":"object","properties":{"upgrade_url":{"type":"string","description":"Where to choose a plan or update the card: Settings, Plan & billing, in the dashboard.","example":"https://app.getvindex.com/settings#billing"},"plan":{"type":"string","enum":["none","starter","growth","scale","enterprise"],"description":"The plan the request was decided on."},"state":{"type":"string","enum":["none","trialing","active","past_due","paused","inactive"]},"limit":{"type":"string","description":"`plan_required` for a counted limit: `policies`, `rules`, `reviewer_seats`, `live_checks`, `test_checks_per_month`."},"allowed":{"type":"integer"},"used":{"type":"integer"},"paused_since":{"type":"string"},"ended_at":{"type":["string","null"]}},"required":["upgrade_url","plan","state"]}]},"CheckRequest":{"type":"object","properties":{"input":{"type":"object","properties":{"prompt":{"type":"string","minLength":1,"maxLength":10000},"negative_prompt":{"type":"string","maxLength":5000},"context":{"type":"array","items":{"type":"string","maxLength":5000},"maxItems":20,"description":"Surrounding text (earlier chat turns, a title). Stored with the decision; not screened yet."}},"required":["prompt"]},"policy":{"type":"string","minLength":1,"maxLength":64,"description":"Policy id. Defaults to the tenant's default policy."},"user":{"type":"string","minLength":1,"maxLength":128,"description":"Your id for the end user this prompt is from. Stored with the decision; rules count, tag and pause per user. A paused user's checks are blocked."},"policy_version":{"type":"integer","minimum":1,"description":"Screen against this version of the policy, published or not, instead of its current one. Dry-run only (`X-Vindex-Dry-Run: true`): for comparing versions."},"metadata":{"type":"object","additionalProperties":{},"description":"Your own JSON (at most 4096 bytes), stored with the decision and returned by GET /v1/decisions/:id."}},"required":["input"]},"DecisionPage":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DecisionListItem"}},"next_cursor":{"type":["string","null"],"description":"Pass as `cursor` for the next page; null on the last."}},"required":["data","next_cursor"]},"DecisionListItem":{"type":"object","properties":{"id":{"type":"string"},"outcome":{"$ref":"#/components/schemas/Outcome"},"tags":{"type":"array","items":{"type":"string"}},"policy":{"type":"object","properties":{"id":{"type":["string","null"]},"version":{"type":["integer","null"]}},"required":["id","version"]},"mode":{"$ref":"#/components/schemas/KeyMode"},"dry_run":{"type":"boolean"},"engine_version":{"type":["string","null"]},"latency_ms":{"type":["integer","null"]},"user":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","outcome","tags","policy","mode","dry_run","engine_version","latency_ms","user","created_at"]},"Decision":{"allOf":[{"$ref":"#/components/schemas/CheckResponse"},{"type":"object","properties":{"input":{"type":"object","properties":{"prompt":{"type":"string"},"negative_prompt":{"type":"string"},"context":{"type":"array","items":{"type":"string"}}},"required":["prompt"]},"prompt_redacted":{"type":"boolean","description":"The prompt was blocked with the minors check at or over its review line (by the policy or a reviewer's verdict), so `input` holds only a placeholder. Only a dashboard owner or admin can reveal it, and every reveal is audited."},"prompt_purged":{"type":"boolean","description":"The decision is older than the plan's retention (7, 30 or 365 days), so its prompt, negative prompt, context and metadata were deleted and `input` holds a placeholder. Its outcome, scores and tags stay."},"user":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":{}},"actions":{"$ref":"#/components/schemas/DecisionActions"},"idempotency_key":{"type":["string","null"]},"input_tokens":{"type":["integer","null"]},"created_at":{"type":"string"}},"required":["input","prompt_redacted","prompt_purged","user","metadata","actions","idempotency_key","input_tokens","created_at"]}]},"DecisionActions":{"type":"object","properties":{"review_id":{"type":["string","null"]},"webhook_events":{"type":"array","items":{"type":"string"}},"webhooks_suppressed":{"type":["string","null"],"enum":["dry_run","test_mode","shadow_mode",null]},"shadow_mode":{"type":"boolean"},"user_paused":{"type":"boolean","description":"The request's user is paused by a rule, so it was blocked whatever the checks said."}},"required":["review_id","webhook_events","webhooks_suppressed"]},"Explanation":{"type":"object","properties":{"id":{"type":"string"},"outcome":{"$ref":"#/components/schemas/Outcome"},"dry_run":{"type":"boolean"},"mode":{"$ref":"#/components/schemas/KeyMode"},"summary":{"type":"string"},"decided_by":{"type":["object","null"],"properties":{"check":{"type":"string"},"policy_line":{"type":["string","null"]},"action":{"$ref":"#/components/schemas/Action"}},"required":["check","policy_line","action"]},"policy":{"type":"object","properties":{"id":{"type":["string","null"]},"version":{"type":["integer","null"]},"youth_coded_adult":{"type":"string","enum":["review","block"]},"adult_max_level":{"type":"integer"}},"required":["id","version"]},"checks":{"type":"array","items":{"type":"object","properties":{"check":{"type":"string"},"version":{"type":"integer"},"routed":{"type":"string","enum":["act","review","allow"]},"action":{"$ref":"#/components/schemas/Action"},"policy_line":{"type":["string","null"]},"score":{"type":"number"},"review_score":{"type":"number"},"act_line":{"type":"number"},"review_line":{"type":"number"},"adult_level":{"type":"integer"},"explanation":{"type":"string"},"signals":{"type":"array","items":{"type":"object","properties":{"signal":{"type":"string"},"probability":{"type":["number","null"]},"line":{"type":["number","null"]},"text":{"type":"string"}},"required":["signal","probability","line","text"]}},"floors":{"type":"array","items":{"type":"object","properties":{"floor":{"type":"string","enum":["age","lexicon","canon"]},"start":{"type":"integer"},"end":{"type":"integer"},"counted":{"type":"boolean"},"text":{"type":"string"}},"required":["floor","start","end","counted","text"],"additionalProperties":{}}}},"required":["check","version","routed","action","policy_line","score","review_score","act_line","review_line","explanation","signals","floors"]}},"actions":{"allOf":[{"$ref":"#/components/schemas/DecisionActions"},{"type":"object","properties":{"tags":{"type":"array","items":{"type":"string"}},"ran":{"type":"array","items":{"type":"string"}}},"required":["tags","ran"]}]},"engine_version":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","outcome","dry_run","mode","summary","decided_by","policy","checks","actions","engine_version","created_at"]},"Action":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["block"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["review"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["allow"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["tag"]},"tag":{"type":"string","minLength":1}},"required":["type","tag"]}]},"PolicySummary":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"preset":{"type":["string","null"]},"current_version":{"type":["integer","null"]},"default":{"type":"boolean"},"dry_run_version":{"type":["integer","null"],"description":"A version being dry-run on live traffic: logged as dry-run decisions alongside the live ones."},"created_at":{"type":"string"}},"required":["id","name","preset","current_version","default","created_at"]},"PolicyDetail":{"allOf":[{"$ref":"#/components/schemas/PolicySummary"},{"type":"object","properties":{"policy":{"$ref":"#/components/schemas/PolicyDocument"},"versions":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer"},"current":{"type":"boolean"},"created_at":{"type":"string"},"created_by":{"type":["string","null"]}},"required":["version","current","created_at"]}}},"required":["policy","versions"]}]},"PolicyDocument":{"type":["object","null"],"properties":{"version":{"type":"number","enum":[1]},"name":{"type":"string","minLength":1},"checks":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/PolicyCheckRule"},"description":"Per check id (`minors_sexual`, `adult`, `real_person`, `copyrighted_ip`). `minors_sexual` is required and pinned: act 0.5, review 0.3, on_act block."},"adult":{"type":"object","properties":{"max_level":{"type":"integer","minimum":1,"maximum":5}},"required":["max_level"],"description":"Highest adult level (1–5) allowed before `checks.adult.on_act` applies. Interim fixed 0.2-wide bands over the adult score, pending issue #10."},"youth_coded_adult":{"type":"string","enum":["review","block"]},"webhooks":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"events":{"type":"array","items":{"type":"string","enum":["block","review","allow","tag","review.verdict"]},"minItems":1},"secret":{"type":"string","minLength":1,"description":"HMAC-SHA256 signing secret, at least 16 characters. Write-only: reads return \"redacted\", and sending \"redacted\" back keeps the stored secret for that url."}},"required":["url","events","secret"]}},"tags":{"type":"object","additionalProperties":{"type":"object","properties":{"description":{"type":"string"}}}}},"required":["version","name","checks","adult","youth_coded_adult","webhooks","tags"]},"PolicyCheckRule":{"type":"object","properties":{"enabled":{"type":"boolean"},"act":{"type":"number","minimum":0,"maximum":1},"review":{"type":"number","minimum":0,"maximum":1},"on_act":{"$ref":"#/components/schemas/Action"},"on_review":{"$ref":"#/components/schemas/Action"}},"required":["act","review","on_act","on_review"]},"CreatePolicyRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"description":"Defaults to the preset's or document's name."},"preset":{"type":"string","description":"Start from a preset (GET /v1/presets). Exactly one of `preset` and `policy`."},"policy":{"$ref":"#/components/schemas/PolicyDocument"},"default":{"type":"boolean","description":"Make this the tenant's default policy. A tenant's first policy always becomes the default."}}},"PolicyVersion":{"type":"object","properties":{"policy_id":{"type":"string"},"version":{"type":"integer"},"current":{"type":"boolean"},"policy":{"$ref":"#/components/schemas/PolicyDocument"}},"required":["policy_id","version","current","policy"]},"Preset":{"type":"object","properties":{"name":{"type":"string"},"policy":{"$ref":"#/components/schemas/PolicyDocument"}},"required":["name","policy"]},"ReviewPage":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ReviewItem"}},"next_cursor":{"type":["string","null"],"description":"Pass as `cursor` for the next page; null on the last."}},"required":["data","next_cursor"]},"ReviewItem":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["open","allowed","blocked","dismissed"]},"created_at":{"type":"string"},"decision":{"type":"object","properties":{"id":{"type":"string"},"outcome":{"$ref":"#/components/schemas/Outcome"},"tags":{"type":"array","items":{"type":"string"}},"policy":{"type":"object","properties":{"id":{"type":["string","null"]},"version":{"type":["integer","null"]}},"required":["id","version"]},"mode":{"$ref":"#/components/schemas/KeyMode"},"input":{"type":"object","properties":{"prompt":{"type":"string"},"negative_prompt":{"type":"string"},"context":{"type":"array","items":{"type":"string"}}},"required":["prompt"]},"prompt_redacted":{"type":"boolean","description":"The prompt was blocked with the minors check at or over its review line (by the policy or a reviewer's verdict), so `input` holds only a placeholder. Only a dashboard owner or admin can reveal it, and every reveal is audited."},"prompt_purged":{"type":"boolean","description":"The decision is older than the plan's retention (7, 30 or 365 days), so its prompt, negative prompt, context and metadata were deleted and `input` holds a placeholder. Its outcome, scores and tags stay."},"user":{"type":["string","null"]},"latency_ms":{"type":["integer","null"]},"checks":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/CheckScore"}},"created_at":{"type":"string"}},"required":["id","outcome","tags","policy","mode","input","prompt_redacted","prompt_purged","user","latency_ms","checks","created_at"]},"verdict":{"type":["object","null"],"properties":{"verdict":{"type":"string","enum":["allow","block","dismiss"]},"note":{"type":["string","null"]},"by":{"type":["string","null"]},"at":{"type":"string"}},"required":["verdict","note","by","at"]}},"required":["id","status","created_at","decision","verdict"]},"VerdictRequest":{"type":"object","properties":{"verdict":{"type":"string","enum":["allow","block","dismiss"]},"note":{"type":"string","maxLength":2000}},"required":["verdict"]},"CreatedApiKey":{"allOf":[{"$ref":"#/components/schemas/ApiKey"},{"type":"object","properties":{"key":{"type":"string","description":"The full key. Shown only in this response; store it now."}},"required":["key"]}]},"ApiKey":{"type":"object","properties":{"id":{"type":"string"},"prefix":{"type":"string","example":"vx_live_3f2a"},"mode":{"$ref":"#/components/schemas/KeyMode"},"label":{"type":["string","null"]},"created_at":{"type":"string"},"last_used_at":{"type":["string","null"],"description":"Approximate: refreshed at most every few minutes."},"revoked_at":{"type":["string","null"]}},"required":["id","prefix","mode","label","created_at","last_used_at","revoked_at"]},"CreateKeyRequest":{"type":"object","properties":{"mode":{"$ref":"#/components/schemas/KeyMode"},"label":{"type":"string","maxLength":120}},"required":["mode"]},"Usage":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/UsageDay"}},"totals":{"type":"object","properties":{"live":{"type":"object","properties":{"checks":{"type":"integer"},"blocked":{"type":"integer"},"reviewed":{"type":"integer"},"input_tokens":{"type":"integer"}},"required":["checks","blocked","reviewed","input_tokens"]},"test":{"type":"object","properties":{"checks":{"type":"integer"},"blocked":{"type":"integer"},"reviewed":{"type":"integer"},"input_tokens":{"type":"integer"}},"required":["checks","blocked","reviewed","input_tokens"]}},"required":["live","test"]}},"required":["from","to","data","totals"]},"UsageDay":{"type":"object","properties":{"day":{"type":"string"},"mode":{"$ref":"#/components/schemas/KeyMode"},"checks":{"type":"integer"},"blocked":{"type":"integer"},"reviewed":{"type":"integer"},"input_tokens":{"type":"integer"}},"required":["day","mode","checks","blocked","reviewed","input_tokens"]},"Plan":{"type":"object","properties":{"plan":{"type":"string","enum":["none","starter","growth","scale","enterprise"]},"name":{"type":"string","example":"Growth"},"state":{"type":"string","enum":["none","trialing","active","past_due","paused","inactive"],"description":"`none`: no plan, test keys only. `trialing`/`active`: the full plan. `past_due`: a payment failed and is being retried; everything works until `pauses_at`. `paused`: checks answer 402 until it's paid. `inactive`: the plan ended; read-only."},"trial_ends_at":{"type":["string","null"]},"pauses_at":{"type":["string","null"],"description":"`past_due` and `paused`: when checks stop (or stopped)."},"ended_at":{"type":["string","null"]},"cancels_at":{"type":["string","null"],"description":"`active`, set to cancel: when the plan ends."},"limits":{"type":"object","properties":{"included_decisions":{"type":"integer","description":"A month. Past it, overage is billed; nothing is refused."},"policies":{"type":["integer","null"],"description":"null: unlimited."},"rules":{"type":["integer","null"]},"reviewer_seats":{"type":["integer","null"]},"retention_days":{"type":"integer","description":"Decisions older than this lose their prompt text; counts, scores and outcomes stay."},"playground_bulk_rows":{"type":"integer"},"rate_limit_per_minute":{"type":"integer","description":"Per API key."},"live_checks":{"type":"boolean"},"test_checks_per_month":{"type":["integer","null"]}},"required":["included_decisions","policies","rules","reviewer_seats","retention_days","playground_bulk_rows","rate_limit_per_minute","live_checks","test_checks_per_month"]},"usage":{"type":"object","properties":{"policies":{"type":"integer"},"rules":{"type":"integer"},"reviewer_seats":{"type":"integer","description":"Reviewers, plus pending reviewer invites."},"test_checks_this_month":{"type":"integer"}},"required":["policies","rules","reviewer_seats","test_checks_this_month"]},"upgrade_url":{"type":"string"}},"required":["plan","name","state","trial_ends_at","pauses_at","ended_at","cancels_at","limits","usage","upgrade_url"]},"Tenant":{"type":"object","properties":{"id":{"type":"string","example":"ten_0a1b2c3d4e5f60718293a4b5c6d7e8f9"},"name":{"type":"string"},"plan":{"type":"string"},"shadow_mode":{"type":"boolean","description":"Screen and log every check, but open no review item and send no webhook; checks return `shadow_mode: true`. A block by `minors_sexual` is always enforced."},"default_policy_id":{"type":["string","null"]},"weekly_digest":{"type":"boolean","description":"Email owners and admins a digest of the week every Monday at 09:00 UTC."},"created_at":{"type":"string"}},"required":["id","name","plan","shadow_mode","default_policy_id","weekly_digest","created_at"]},"UpdateTenantRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"shadow_mode":{"type":"boolean"},"weekly_digest":{"type":"boolean"}}}},"parameters":{}},"paths":{"/":{"get":{"tags":["Meta"],"summary":"Pointers to the docs and health check","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"},"docs":{"type":"string"},"openapi":{"type":"string"},"health":{"type":"string"}},"required":["name","version","docs","openapi","health"]}}}}}}},"/health":{"get":{"tags":["Meta"],"summary":"Liveness and worker version","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"version":{"type":"string"},"engine":{"type":"string"}},"required":["ok","version","engine"]}}}}}}},"/v1/check":{"post":{"tags":["Check"],"summary":"Screen a prompt against a policy","description":"Runs every enabled check of the policy in one call to the screening engine, applies the code-side floors and the policy, logs the decision, and (unless dry-run) opens a review item and queues webhooks. `latency_ms` is received → decided; `Server-Timing` breaks it down.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Retries with the same key (per tenant) return the first decision instead of screening again."},"required":false,"description":"Retries with the same key (per tenant) return the first decision instead of screening again.","name":"idempotency-key","in":"header"},{"schema":{"type":"string","description":"`true`: evaluate and log, but open no review item and send no webhooks."},"required":false,"description":"`true`: evaluate and log, but open no review item and send no webhooks.","name":"x-vindex-dry-run","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckRequest"}}}},"responses":{"200":{"description":"The decision. `Idempotent-Replayed: true` when returned for a repeated Idempotency-Key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckResponse"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"402":{"description":"Nothing was screened. `subscription_paused`: a payment has been failing for 14 days. `subscription_inactive`: the plan has ended (read-only). `plan_required`: a live key on a workspace with no plan, or a test key past the free allowance.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/PlanProblem"}}}},"404":{"description":"`policy` names no policy of this tenant (`policy_not_found`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"No `policy` and no default policy (`no_default_policy`), or an Idempotency-Key reused with a different body (`idempotency_key_reused`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"The screening engine is unavailable (`screening_unavailable`); nothing was decided. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/decisions":{"get":{"tags":["Decisions"],"summary":"List decisions, newest first","description":"Decisions made in the key's mode only: a test key lists test decisions, a live key live ones.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"$ref":"#/components/schemas/Outcome"},"required":false,"name":"outcome","in":"query"},{"schema":{"type":"string","maxLength":64,"description":"Policy id."},"required":false,"description":"Policy id.","name":"policy","in":"query"},{"schema":{"allOf":[{"$ref":"#/components/schemas/KeyMode"},{"description":"Must be the key's own mode, if given: a key lists its own mode's decisions only."}]},"required":false,"description":"Must be the key's own mode, if given: a key lists its own mode's decisions only.","name":"mode","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"`false` leaves out dry runs; `true` lists only them."},"required":false,"description":"`false` leaves out dry runs; `true` lists only them.","name":"dry_run","in":"query"},{"schema":{"type":"string","description":"Inclusive lower bound on created_at (ISO 8601)."},"required":false,"description":"Inclusive lower bound on created_at (ISO 8601).","name":"since","in":"query"},{"schema":{"type":"string","description":"Exclusive upper bound on created_at (ISO 8601)."},"required":false,"description":"Exclusive upper bound on created_at (ISO 8601).","name":"until","in":"query"},{"schema":{"type":"string","enum":["minors_sexual","adult","real_person","copyrighted_ip"],"description":"Only decisions where this check decided or reached its review line."},"required":false,"description":"Only decisions where this check decided or reached its review line.","name":"check","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":128,"description":"Only decisions for this end user (`user` on POST /v1/check)."},"required":false,"description":"Only decisions for this end user (`user` on POST /v1/check).","name":"user","in":"query"},{"schema":{"type":"string","pattern":"^dec_[0-9a-f]{0,32}$","description":"Decision ids starting with this."},"required":false,"description":"Decision ids starting with this.","name":"id_prefix","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","maxLength":512},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"A page of decisions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecisionPage"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"`mode` isn't the key's own mode (`mode_forbidden`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/decisions/{id}":{"get":{"tags":["Decisions"],"summary":"Get a decision","security":[{"bearerAuth":[]}],"description":"A prompt blocked by the minors check comes back as a placeholder with `prompt_redacted: true`. A prompt older than the plan's retention has been deleted: `prompt_purged: true`. A decision made in the other mode (live for a test key, test for a live key) is a 404.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"dec_3f2a0c9e8b7d4c6a9f1e2d3c4b5a6978","description":"Decision id"},"required":true,"description":"Decision id","name":"id","in":"path"},{"schema":{"type":"string","enum":["1","true"],"description":"Return a redacted prompt in full. Dashboard owners and admins only (`reveal_forbidden` otherwise); every reveal is written to the audit log."},"required":false,"description":"Return a redacted prompt in full. Dashboard owners and admins only (`reveal_forbidden` otherwise); every reveal is written to the audit log.","name":"reveal","in":"query"}],"responses":{"200":{"description":"The decision, with its input, metadata and actions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Decision"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"`reveal` from anyone but a dashboard owner or admin (`reveal_forbidden`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such decision for this tenant.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/decisions/{id}/explain":{"get":{"tags":["Decisions"],"summary":"Explain a decision in plain words","description":"Per check: the signals that fired with their probability against the line they crossed, the minors floors hit (rule and character offsets, never the matched text), which policy line decided the outcome, and what actions ran.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"dec_3f2a0c9e8b7d4c6a9f1e2d3c4b5a6978","description":"Decision id"},"required":true,"description":"Decision id","name":"id","in":"path"}],"responses":{"200":{"description":"The explanation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Explanation"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such decision for this tenant.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/policies":{"get":{"tags":["Policies"],"summary":"List policies","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Every policy of the tenant, newest first.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PolicySummary"}}},"required":["data"]}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Policies"],"summary":"Create a policy from a preset or a document","description":"Creates the policy with version 1 published. The tenant's first policy becomes its default. Starter includes one policy.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePolicyRequest"}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyDetail"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"402":{"description":"The plan's policies are all used (`plan_required`, `limit: policies`), or the plan has ended (`subscription_inactive`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/PlanProblem"}}}},"422":{"description":"The document failed policy validation (`invalid_policy`, with `issues`), or the preset doesn't exist.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/policies/{id}":{"get":{"tags":["Policies"],"summary":"Get a policy, its current document and its versions","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"pol_8c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f","description":"Policy id"},"required":true,"description":"Policy id","name":"id","in":"path"}],"responses":{"200":{"description":"The policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyDetail"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such policy (or version) for this tenant.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/policies/{id}/versions":{"post":{"tags":["Policies"],"summary":"Add a new (unpublished) version","description":"Validates the document and stores it as the next version. It takes effect only once published.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"pol_8c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f","description":"Policy id"},"required":true,"description":"Policy id","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyDocument"}}}},"responses":{"201":{"description":"The new version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyVersion"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"402":{"description":"The workspace's plan has ended, so it's read-only (`subscription_inactive`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/PlanProblem"}}}},"404":{"description":"No such policy (or version) for this tenant.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The document failed policy validation (`invalid_policy`, with `issues`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/policies/{id}/publish":{"post":{"tags":["Policies"],"summary":"Publish a version","description":"Makes the version current. Checks pick it up once the policy cache entry is gone everywhere: usually within ~60 s (KV is eventually consistent), at most 5 minutes if a check was caching the old version as you published.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"pol_8c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f","description":"Policy id"},"required":true,"description":"Policy id","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"integer","minimum":1}},"required":["version"]}}}},"responses":{"200":{"description":"Published.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicySummary"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"402":{"description":"The workspace's plan has ended, so it's read-only (`subscription_inactive`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/PlanProblem"}}}},"404":{"description":"No such policy (or version) for this tenant.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The version no longer passes validation (`invalid_policy`, with `issues`), e.g. a webhook on plain http://. Save a fixed version and publish that.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/policies/{id}/default":{"post":{"tags":["Policies"],"summary":"Make a policy the tenant's default","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"pol_8c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f","description":"Policy id"},"required":true,"description":"Policy id","name":"id","in":"path"}],"responses":{"200":{"description":"Now the default.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicySummary"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"402":{"description":"The workspace's plan has ended, so it's read-only (`subscription_inactive`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/PlanProblem"}}}},"404":{"description":"No such policy (or version) for this tenant.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/policies/{id}/versions/{version}":{"get":{"tags":["Policies"],"summary":"Get one version of a policy","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"pol_8c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f","description":"Policy id"},"required":true,"description":"Policy id","name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"example":2},"required":true,"name":"version","in":"path"}],"responses":{"200":{"description":"The version's document (webhook secrets redacted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyVersion"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such policy (or version) for this tenant.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/presets":{"get":{"tags":["Policies"],"summary":"List preset policies","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The shipped presets.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Preset"}}},"required":["data"]}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/review":{"get":{"tags":["Review"],"summary":"List review items, oldest first","description":"Open items by default, for decisions made in the key's mode only. Each item carries the decision's input so a reviewer can rule on it, except a prompt blocked (by a verdict) with the minors check at or over its review line: that one is a placeholder with `prompt_redacted: true`.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["open","allowed","blocked","dismissed"],"default":"open"},"required":false,"name":"status","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","maxLength":512},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","enum":["1","true"],"description":"Return a redacted prompt in full. Dashboard owners and admins only (`reveal_forbidden` otherwise); every reveal is written to the audit log."},"required":false,"description":"Return a redacted prompt in full. Dashboard owners and admins only (`reveal_forbidden` otherwise); every reveal is written to the audit log.","name":"reveal","in":"query"}],"responses":{"200":{"description":"A page of review items.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewPage"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"`reveal` from anyone but a dashboard owner or admin (`reveal_forbidden`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/review/{id}/verdict":{"post":{"tags":["Review"],"summary":"Rule on a review item","description":"Records `allow`, `block` or `dismiss` on an open item. Webhooks of the decision's policy subscribed to `review.verdict` are notified (never for a test-mode decision).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"rev_0a1b2c3d4e5f60718293a4b5c6d7e8f9","description":"Review item id"},"required":true,"description":"Review item id","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerdictRequest"}}}},"responses":{"200":{"description":"The item, with its verdict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewItem"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such review item for this tenant, in the key's mode.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The item already has a verdict (`already_decided`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/keys":{"post":{"tags":["Keys"],"summary":"Create an API key","description":"Returns the full key once; only its SHA-256 hash is stored. An API key creates test-mode keys; live keys are made in the dashboard.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateKeyRequest"}}}},"responses":{"201":{"description":"Created. Store `key` now: it is never shown again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedApiKey"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"402":{"description":"The workspace's plan has ended, so it's read-only (`subscription_inactive`). Revoking keys still works.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/PlanProblem"}}}},"403":{"description":"A test-mode key tried to create a live key (`test_key_forbidden`), or a live key did: live keys are made in the dashboard (`dashboard_only`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"tags":["Keys"],"summary":"List API keys","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Every key of the tenant, revoked ones included. Never the key itself.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}}},"required":["data"]}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/keys/{id}":{"delete":{"tags":["Keys"],"summary":"Revoke an API key","description":"Idempotent. Takes effect everywhere within about two minutes (the key's auth cache entry is deleted, KV is eventually consistent, and cached lookups expire after 60 s). You can't revoke the key making the request.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"key_5e6f708192a3b4c5d6e7f8091a2b3c4d","description":"API key id"},"required":true,"description":"API key id","name":"id","in":"path"}],"responses":{"200":{"description":"The revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKey"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"A test-mode key tried to revoke a live key (`test_key_forbidden`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No such key for this tenant.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The key making the request can't revoke itself (`cannot_revoke_current_key`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/usage":{"get":{"tags":["Usage"],"summary":"Daily usage","description":"Checks, blocks, reviews and screening input tokens per UTC day, for the key's mode only. Defaults to the last 30 days.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":false,"name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":false,"name":"to","in":"query"},{"schema":{"allOf":[{"$ref":"#/components/schemas/KeyMode"},{"description":"Must be the key's own mode, if given."}]},"required":false,"description":"Must be the key's own mode, if given.","name":"mode","in":"query"}],"responses":{"200":{"description":"Usage in [from, to], inclusive.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Usage"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"`mode` isn't the key's own mode (`mode_forbidden`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/plan":{"get":{"tags":["Tenant"],"summary":"The workspace's plan, its limits and what's used","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Plan"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/tenant":{"get":{"tags":["Tenant"],"summary":"The key's tenant, including shadow mode","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The tenant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tenant"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Tenant"],"summary":"Rename the tenant or turn shadow mode on or off","description":"A live key can rename the tenant. Shadow mode is switched in the dashboard (Settings), and reaches every edge within about two minutes. A test-mode key can't change the tenant.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTenantRequest"}}}},"responses":{"200":{"description":"The tenant, updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tenant"}}}},"400":{"description":"Invalid request (malformed JSON, or the body/query failed validation).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"A test-mode key (`test_key_forbidden`), an API key changing shadow mode (`dashboard_only`), or a dashboard reviewer (`role_forbidden`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded for this API key. See `Retry-After`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}},"webhooks":{}}