{"openapi":"3.1.0","info":{"title":"Driftstack API","version":"0.0.1","description":"Driftstack API — stealth iPhone Safari automation. Pre-launch contract; subject to change.\n\n## Team RBAC: X-Driftstack-Account header (V-326e)\n\nMembers of a team can scope any /v1/* request to the OWNER's resources by passing\nthe `X-Driftstack-Account: acc_<owner-uuid>` request header. The server validates that\nthe calling account is on the team referenced by the header.\n\n- Read endpoints (GET): both `member` and `admin` roles allowed.\n- Write endpoints (POST / PATCH / DELETE / api-keys rotate): `admin` role only;\n  `member` role gets 403.\n\nEndpoints honoring the header: /v1/sessions (+ all session sub-paths), /v1/profiles,\n/v1/api-keys (+ /:id/rotate), /v1/webhooks (+ /:id/deliveries + replay),\n/v1/account/audit-log (+ export), /v1/account/email-preferences, /v1/usage,\n/v1/usage/series.\n\nEndpoints that do NOT honor the header: /v1/team/*, /v1/account/me (always\nreturns the caller's own profile + their team list), /v1/auth/*.\n\nSee `docs.driftstack.dev/api/team` for full details.","license":{"name":"MIT"},"contact":{"name":"Driftstack","url":"https://github.com/driftstackdev/driftstack-api"}},"servers":[{"url":"https://api.driftstack.dev","description":"Production (placeholder)"}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API key"}},"schemas":{"Account":{"type":"object","properties":{"id":{"type":"string","pattern":"^acc_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"email":{"type":"string","format":"email"},"name":{"type":["string","null"]},"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"status":{"type":"string","enum":["active","suspended","deleted"]},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","email","name","tier","status","created_at","updated_at"]},"AccountMeResponse":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string","format":"email"},"name":{"type":["string","null"]},"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"status":{"type":"string","enum":["active","suspended","deleted"]},"timezone":{"type":["string","null"]},"slug":{"type":["string","null"]},"region":{"type":["string","null"],"enum":["us","eu","apac"]},"avatar_url":{"type":["string","null"]},"mfa_enrolled":{"type":"boolean"},"concurrent_session_cap":{"type":"integer","minimum":0},"concurrent_session_active":{"type":"integer","minimum":0},"profile_cap":{"type":["integer","null"],"minimum":0},"profile_count":{"type":"integer","minimum":0},"teams":{"type":"array","items":{"type":"object","properties":{"owner_account_id":{"type":"string"},"role":{"type":"string","enum":["admin","member"]},"membership_id":{"type":"string"}},"required":["owner_account_id","role","membership_id"]}}},"required":["id","email","name","tier","status","timezone","slug","region","avatar_url","mfa_enrolled","concurrent_session_cap","concurrent_session_active","profile_cap","profile_count","teams"]},"UpdateAccountMeRequest":{"type":"object","properties":{"name":{"type":["string","null"],"minLength":1,"maxLength":120},"timezone":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[A-Za-z]+(?:\\/[A-Za-z0-9_+-]+)+$"},"slug":{"type":["string","null"],"minLength":3,"maxLength":32,"pattern":"^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$"},"region":{"type":["string","null"],"enum":["us","eu","apac"]}}},"ApiKey":{"type":"object","properties":{"id":{"type":"string","pattern":"^key_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"name":{"type":"string"},"key_prefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","admin","account_owner","driftstack_internal_admin","gui_control"]}},"last_used_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"revoked_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"expires_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","name","key_prefix","scopes","last_used_at","revoked_at","expires_at","created_at"]},"Session":{"type":"object","properties":{"id":{"type":"string","pattern":"^ses_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"account_id":{"type":"string","pattern":"^acc_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"api_key_id":{"type":"string","pattern":"^key_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"status":{"type":"string","enum":["creating","ready","busy","destroyed","errored"]},"archetype":{"type":"string","minLength":3,"maxLength":60,"pattern":"^[a-z0-9_]+$"},"purpose":{"type":"string","enum":["production_customer","cumulative_rig_validation","test_domain_probe"]},"label":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":{}},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_state_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"destroyed_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","account_id","api_key_id","status","archetype","purpose","label","metadata","created_at","updated_at","last_state_at","destroyed_at"]},"SessionState":{"type":"object","properties":{"url":{"type":["string","null"],"format":"uri"},"title":{"type":["string","null"]},"cookies":{"type":"array","items":{"type":"object","additionalProperties":{}}},"local_storage":{"type":"object","additionalProperties":{"type":"string"}},"captured_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["url","title","cookies","local_storage","captured_at"]},"Problem":{"type":"object","properties":{"type":{"type":"string","format":"uri","description":"Stable URI identifying the problem class. Clients switch on this."},"title":{"type":"string"},"status":{"type":"integer","minimum":100,"maximum":599},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"],"additionalProperties":{},"description":"RFC 7807 problem details"},"UsagePeriodSummary":{"type":"object","properties":{"period_start":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"period_end":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"totals":{"type":"object","properties":{"session_minute":{"type":"integer","minimum":0},"navigate":{"type":"integer","minimum":0},"interact":{"type":"integer","minimum":0},"wait":{"type":"integer","minimum":0},"state_capture":{"type":"integer","minimum":0},"screenshot_capture":{"type":"integer","minimum":0}}},"quotas":{"type":"object","properties":{"session_minute":{"type":["integer","null"],"minimum":0},"navigate":{"type":["integer","null"],"minimum":0},"interact":{"type":["integer","null"],"minimum":0},"wait":{"type":["integer","null"],"minimum":0},"state_capture":{"type":["integer","null"],"minimum":0},"screenshot_capture":{"type":["integer","null"],"minimum":0}}}},"required":["period_start","period_end","tier","totals","quotas"]},"PaginationQuery":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":100,"default":50},"cursor":{"type":"string"}}},"CreateSessionRequest":{"type":"object","properties":{"archetype":{"type":"string","minLength":3,"maxLength":60,"pattern":"^[a-z0-9_]+$"},"purpose":{"type":"string","enum":["production_customer","cumulative_rig_validation","test_domain_probe"]},"label":{"type":"string","maxLength":120},"metadata":{"type":"object","additionalProperties":{}}}},"CreateSessionResponse":{"type":"object","properties":{"id":{"type":"string","pattern":"^ses_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"account_id":{"type":"string","pattern":"^acc_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"api_key_id":{"type":"string","pattern":"^key_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"status":{"type":"string","enum":["creating","ready","busy","destroyed","errored"]},"archetype":{"type":"string","minLength":3,"maxLength":60,"pattern":"^[a-z0-9_]+$"},"purpose":{"type":"string","enum":["production_customer","cumulative_rig_validation","test_domain_probe"]},"label":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":{}},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_state_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"destroyed_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","account_id","api_key_id","status","archetype","purpose","label","metadata","created_at","updated_at","last_state_at","destroyed_at"]},"NavigateRequest":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"timeout_ms":{"type":"integer","minimum":1000,"maximum":120000},"wait_until":{"type":"string","enum":["load","domcontentloaded","networkidle"],"default":"load"}},"required":["url"]},"NavigateResponse":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"status":{"type":"integer","minimum":100,"maximum":599},"final_url":{"type":"string","format":"uri"},"duration_ms":{"type":"integer","minimum":0}},"required":["url","status","final_url","duration_ms"]},"InteractRequest":{"type":"object","properties":{"action":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["tap"]},"selector":{"type":"string","minLength":1}},"required":["kind","selector"]},{"type":"object","properties":{"kind":{"type":"string","enum":["type"]},"selector":{"type":"string","minLength":1},"text":{"type":"string","maxLength":10000},"delay_ms":{"type":"integer","minimum":0,"maximum":500}},"required":["kind","selector","text"]},{"type":"object","properties":{"kind":{"type":"string","enum":["scroll"]},"selector":{"type":"string","minLength":1},"delta_x":{"type":"integer","default":0},"delta_y":{"type":"integer","default":0}},"required":["kind"]},{"type":"object","properties":{"kind":{"type":"string","enum":["press"]},"key":{"type":"string","minLength":1,"maxLength":20}},"required":["kind","key"]}]},"timeout_ms":{"type":"integer","minimum":100,"maximum":60000}},"required":["action"]},"InteractResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"duration_ms":{"type":"integer","minimum":0}},"required":["ok","duration_ms"]},"WaitRequest":{"type":"object","properties":{"condition":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["selector"]},"selector":{"type":"string","minLength":1}},"required":["kind","selector"]},{"type":"object","properties":{"kind":{"type":"string","enum":["selector_hidden"]},"selector":{"type":"string","minLength":1}},"required":["kind","selector"]},{"type":"object","properties":{"kind":{"type":"string","enum":["url_matches"]},"pattern":{"type":"string","minLength":1}},"required":["kind","pattern"]},{"type":"object","properties":{"kind":{"type":"string","enum":["time"]},"ms":{"type":"integer","minimum":0,"maximum":60000}},"required":["kind","ms"]}]},"timeout_ms":{"type":"integer","minimum":100,"maximum":120000}},"required":["condition"]},"WaitResponse":{"type":"object","properties":{"satisfied":{"type":"boolean"},"duration_ms":{"type":"integer","minimum":0}},"required":["satisfied","duration_ms"]},"CaptureRequest":{"type":"object","properties":{"kind":{"type":"string","enum":["screenshot","dom_snapshot","pdf"]},"full_page":{"type":"boolean","default":false}},"required":["kind"]},"CaptureResponse":{"type":"object","properties":{"kind":{"type":"string","enum":["screenshot","dom_snapshot","pdf"]},"data":{"type":"string"},"encoding":{"type":"string","enum":["base64","utf8"]},"byte_size":{"type":"integer","minimum":0},"duration_ms":{"type":"integer","minimum":0}},"required":["kind","data","encoding","byte_size","duration_ms"]},"CreateApiKeyRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","admin","account_owner","driftstack_internal_admin","gui_control"]},"minItems":1},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["name","scopes"]},"CreateApiKeyResponse":{"type":"object","properties":{"id":{"type":"string","pattern":"^key_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"name":{"type":"string"},"key_prefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","admin","account_owner","driftstack_internal_admin","gui_control"]}},"last_used_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"revoked_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"expires_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"plaintext":{"type":"string","description":"The plaintext key. Shown once at creation; not retrievable later."}},"required":["id","name","key_prefix","scopes","last_used_at","revoked_at","expires_at","created_at","plaintext"]},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string","pattern":"^whk_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"url":{"type":"string","format":"uri"},"secret_prefix":{"type":"string"},"prev_secret_prefix":{"type":["string","null"]},"rotation_grace_expires_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"events":{"type":"array","items":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked","test.ping"]}},"description":{"type":["string","null"]},"active":{"type":"boolean"},"consecutive_failures":{"type":"integer","minimum":0},"last_success_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_failure_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"disabled_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"delivery_counts":{"type":"object","properties":{"delivered":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"dlq":{"type":"integer","minimum":0}},"required":["delivered","failed","dlq"]},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","url","secret_prefix","prev_secret_prefix","rotation_grace_expires_at","events","description","active","consecutive_failures","last_success_at","last_failure_at","disabled_at","delivery_counts","created_at"]},"CreateWebhookRequest":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked"]},"minItems":1,"maxItems":10},"description":{"type":"string","maxLength":200}},"required":["url","events"]},"CreateWebhookResponse":{"type":"object","properties":{"id":{"type":"string","pattern":"^whk_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"url":{"type":"string","format":"uri"},"secret_prefix":{"type":"string"},"prev_secret_prefix":{"type":["string","null"]},"rotation_grace_expires_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"events":{"type":"array","items":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked","test.ping"]}},"description":{"type":["string","null"]},"active":{"type":"boolean"},"consecutive_failures":{"type":"integer","minimum":0},"last_success_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_failure_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"disabled_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"delivery_counts":{"type":"object","properties":{"delivered":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"dlq":{"type":"integer","minimum":0}},"required":["delivered","failed","dlq"]},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"secret":{"type":"string","description":"Plaintext signing secret. Returned ONCE; not retrievable later."}},"required":["id","url","secret_prefix","prev_secret_prefix","rotation_grace_expires_at","events","description","active","consecutive_failures","last_success_at","last_failure_at","disabled_at","delivery_counts","created_at","secret"]},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string","pattern":"^wdl_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"webhook_id":{"type":"string","pattern":"^whk_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"event_id":{"type":"string","format":"uuid"},"event_type":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked","test.ping"]},"status":{"type":"string","enum":["pending","in_flight","delivered","failed","dlq"]},"attempts":{"type":"integer","minimum":0},"next_attempt_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_response_status":{"type":["integer","null"]},"last_response_excerpt":{"type":["string","null"]},"last_error":{"type":["string","null"]},"delivered_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","webhook_id","event_id","event_type","status","attempts","next_attempt_at","last_response_status","last_response_excerpt","last_error","delivered_at","created_at"]},"ListDeliveriesQuery":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":100,"default":50},"cursor":{"type":"string"},"status":{"type":"string","enum":["pending","in_flight","delivered","failed","dlq"]}}},"AdminAccount":{"type":"object","properties":{"id":{"type":"string","pattern":"^acc_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"email":{"type":"string","format":"email"},"name":{"type":["string","null"]},"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"status":{"type":"string","enum":["active","suspended","deleted"]},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","email","name","tier","status","created_at","updated_at"]},"AdminAuditLogEntry":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"admin_account_id":{"type":"string"},"admin_key_id":{"type":"string"},"action":{"type":"string","enum":["account.tier_changed","account.suspended","account.unsuspended","webhook_delivery.replayed","webhook_delivery.requeued","rate_limit_override.set","rate_limit_override.cleared","session.destroyed_by_admin","api_key.revoked_by_admin","audit_note.added","refund.recorded","incident.created","incident.updated","incident.resolved","status_subscriber.force_unsubscribed","status_subscriber.purged"]},"target_account_id":{"type":["string","null"]},"target_resource_id":{"type":["string","null"]},"input_payload":{"type":["object","null"],"additionalProperties":{}},"result":{"type":"string"},"ip_address":{"type":["string","null"]},"timestamp":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","admin_account_id","admin_key_id","action","target_account_id","target_resource_id","input_payload","result","ip_address","timestamp"]},"RotateApiKeyResponse":{"type":"object","properties":{"id":{"type":"string","pattern":"^key_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"name":{"type":"string"},"key_prefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","admin","account_owner","driftstack_internal_admin","gui_control"]}},"last_used_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"revoked_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"expires_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"plaintext":{"type":"string","description":"The plaintext key. Shown once at creation; not retrievable later."},"rotated_from":{"type":"string"},"grace_period_ends_at":{"type":"string"}},"required":["id","name","key_prefix","scopes","last_used_at","revoked_at","expires_at","created_at","plaintext","rotated_from","grace_period_ends_at"]},"RotateApiKeyRequest":{"type":"object","properties":{"name":{"type":"string"}}},"TeamInviteRequest":{"type":"object","properties":{"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["member","admin"]}},"required":["email"]},"TeamInvite":{"type":"object","properties":{"id":{"type":"string","description":"Prefixed invite id (inv_<uuid>)"},"owner_account_id":{"type":"string"},"invitee_email":{"type":"string"},"role":{"type":"string","enum":["member","admin"]},"expires_at":{"type":"string"},"invited_by_account_id":{"type":["string","null"]},"accepted_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","owner_account_id","invitee_email","role","expires_at","invited_by_account_id","accepted_at","created_at"]},"TeamMember":{"type":"object","properties":{"id":{"type":"string","description":"Prefixed membership id (mem_<uuid>)"},"owner_account_id":{"type":"string"},"member_account_id":{"type":"string"},"member_email":{"type":"string"},"role":{"type":"string","enum":["member","admin"]},"invited_at":{"type":"string"},"accepted_at":{"type":"string"},"invited_by_account_id":{"type":["string","null"]}},"required":["id","owner_account_id","member_account_id","member_email","role","invited_at","accepted_at","invited_by_account_id"]},"TeamAcceptRequest":{"type":"object","properties":{"token":{"type":"string","minLength":20}},"required":["token"]},"TeamOwner":{"type":"object","properties":{"owner_account_id":{"type":"string"},"role":{"type":"string","enum":["member","admin"]},"membership_id":{"type":"string"}},"required":["owner_account_id","role","membership_id"]}},"parameters":{}},"paths":{"/v1/sessions":{"post":{"summary":"Create a session","tags":["Sessions"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"archetype":{"type":"string","minLength":3,"maxLength":60,"pattern":"^[a-z0-9_]+$"},"purpose":{"type":"string","enum":["production_customer","cumulative_rig_validation","test_domain_probe"]},"label":{"type":"string","maxLength":120},"metadata":{"type":"object","additionalProperties":{}}}}}}},"responses":{"201":{"description":"Session created.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^ses_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"account_id":{"type":"string","pattern":"^acc_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"api_key_id":{"type":"string","pattern":"^key_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"status":{"type":"string","enum":["creating","ready","busy","destroyed","errored"]},"archetype":{"type":"string","minLength":3,"maxLength":60,"pattern":"^[a-z0-9_]+$"},"purpose":{"type":"string","enum":["production_customer","cumulative_rig_validation","test_domain_probe"]},"label":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":{}},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_state_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"destroyed_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","account_id","api_key_id","status","archetype","purpose","label","metadata","created_at","updated_at","last_state_at","destroyed_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"summary":"List sessions for the calling account","tags":["Sessions"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"Paginated list of sessions.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^ses_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"account_id":{"type":"string","pattern":"^acc_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"api_key_id":{"type":"string","pattern":"^key_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"status":{"type":"string","enum":["creating","ready","busy","destroyed","errored"]},"archetype":{"type":"string","minLength":3,"maxLength":60,"pattern":"^[a-z0-9_]+$"},"purpose":{"type":"string","enum":["production_customer","cumulative_rig_validation","test_domain_probe"]},"label":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":{}},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_state_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"destroyed_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","account_id","api_key_id","status","archetype","purpose","label","metadata","created_at","updated_at","last_state_at","destroyed_at"]}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["data","has_more","next_cursor"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sessions/{id}/navigate":{"post":{"summary":"Navigate to a URL within a session","tags":["Sessions"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Prefixed session id (ses_<uuid>)"},"required":true,"description":"Prefixed session id (ses_<uuid>)","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"timeout_ms":{"type":"integer","minimum":1000,"maximum":120000},"wait_until":{"type":"string","enum":["load","domcontentloaded","networkidle"],"default":"load"}},"required":["url"]}}}},"responses":{"200":{"description":"Navigation completed.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"status":{"type":"integer","minimum":100,"maximum":599},"final_url":{"type":"string","format":"uri"},"duration_ms":{"type":"integer","minimum":0}},"required":["url","status","final_url","duration_ms"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Session not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"410":{"description":"Session destroyed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"502":{"description":"Driver-level error during navigation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sessions/{id}/interact":{"post":{"summary":"Send an interaction (tap / type / scroll / press) to the session","tags":["Sessions"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["tap"]},"selector":{"type":"string","minLength":1}},"required":["kind","selector"]},{"type":"object","properties":{"kind":{"type":"string","enum":["type"]},"selector":{"type":"string","minLength":1},"text":{"type":"string","maxLength":10000},"delay_ms":{"type":"integer","minimum":0,"maximum":500}},"required":["kind","selector","text"]},{"type":"object","properties":{"kind":{"type":"string","enum":["scroll"]},"selector":{"type":"string","minLength":1},"delta_x":{"type":"integer","default":0},"delta_y":{"type":"integer","default":0}},"required":["kind"]},{"type":"object","properties":{"kind":{"type":"string","enum":["press"]},"key":{"type":"string","minLength":1,"maxLength":20}},"required":["kind","key"]}]},"timeout_ms":{"type":"integer","minimum":100,"maximum":60000}},"required":["action"]}}}},"responses":{"200":{"description":"Interaction completed.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"duration_ms":{"type":"integer","minimum":0}},"required":["ok","duration_ms"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Session not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"410":{"description":"Session destroyed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"502":{"description":"Driver-level error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sessions/{id}/wait":{"post":{"summary":"Wait for a session-side condition (selector, url, time)","tags":["Sessions"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"condition":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["selector"]},"selector":{"type":"string","minLength":1}},"required":["kind","selector"]},{"type":"object","properties":{"kind":{"type":"string","enum":["selector_hidden"]},"selector":{"type":"string","minLength":1}},"required":["kind","selector"]},{"type":"object","properties":{"kind":{"type":"string","enum":["url_matches"]},"pattern":{"type":"string","minLength":1}},"required":["kind","pattern"]},{"type":"object","properties":{"kind":{"type":"string","enum":["time"]},"ms":{"type":"integer","minimum":0,"maximum":60000}},"required":["kind","ms"]}]},"timeout_ms":{"type":"integer","minimum":100,"maximum":120000}},"required":["condition"]}}}},"responses":{"200":{"description":"Wait resolved (satisfied or timed out).","content":{"application/json":{"schema":{"type":"object","properties":{"satisfied":{"type":"boolean"},"duration_ms":{"type":"integer","minimum":0}},"required":["satisfied","duration_ms"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sessions/{id}/state":{"get":{"summary":"Snapshot current session state (URL, title, cookies, localStorage)","tags":["Sessions"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Session state.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":["string","null"],"format":"uri"},"title":{"type":["string","null"]},"cookies":{"type":"array","items":{"type":"object","additionalProperties":{}}},"local_storage":{"type":"object","additionalProperties":{"type":"string"}},"captured_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["url","title","cookies","local_storage","captured_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sessions/{id}/capture":{"post":{"summary":"Capture a screenshot, DOM snapshot, or PDF of the session","tags":["Sessions"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["screenshot","dom_snapshot","pdf"]},"full_page":{"type":"boolean","default":false}},"required":["kind"]}}}},"responses":{"200":{"description":"Capture produced.","content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["screenshot","dom_snapshot","pdf"]},"data":{"type":"string"},"encoding":{"type":"string","enum":["base64","utf8"]},"byte_size":{"type":"integer","minimum":0},"duration_ms":{"type":"integer","minimum":0}},"required":["kind","data","encoding","byte_size","duration_ms"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sessions/{id}":{"delete":{"summary":"Destroy a session","tags":["Sessions"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Session destroyed."},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/api-keys":{"post":{"summary":"Create an API key (returns plaintext once, never retrievable later)","tags":["API keys"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","admin","account_owner","driftstack_internal_admin","gui_control"]},"minItems":1},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["name","scopes"]}}}},"responses":{"201":{"description":"Key created. The plaintext is in the response — store it now.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^key_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"name":{"type":"string"},"key_prefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","admin","account_owner","driftstack_internal_admin","gui_control"]}},"last_used_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"revoked_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"expires_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"plaintext":{"type":"string","description":"The plaintext key. Shown once at creation; not retrievable later."}},"required":["id","name","key_prefix","scopes","last_used_at","revoked_at","expires_at","created_at","plaintext"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"summary":"List API keys for the calling account","tags":["API keys"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"List of keys (plaintext never included).","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^key_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"name":{"type":"string"},"key_prefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","admin","account_owner","driftstack_internal_admin","gui_control"]}},"last_used_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"revoked_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"expires_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","name","key_prefix","scopes","last_used_at","revoked_at","expires_at","created_at"]}}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/api-keys/{id}":{"delete":{"summary":"Revoke an API key","tags":["API keys"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Key revoked."},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Key not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/api-keys/{id}/rotate":{"post":{"summary":"Rotate an API key (V-296). 24h grace; new plaintext shown once","tags":["API keys"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateApiKeyRequest"}}}},"responses":{"201":{"description":"New key created with the same scopes; old key auto-revokes at grace_period_ends_at.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateApiKeyResponse"}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Key not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/usage":{"get":{"summary":"Current-period usage totals + tier quotas","tags":["Usage"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Period summary.","content":{"application/json":{"schema":{"type":"object","properties":{"period_start":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"period_end":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"totals":{"type":"object","properties":{"session_minute":{"type":"integer","minimum":0},"navigate":{"type":"integer","minimum":0},"interact":{"type":"integer","minimum":0},"wait":{"type":"integer","minimum":0},"state_capture":{"type":"integer","minimum":0},"screenshot_capture":{"type":"integer","minimum":0}}},"quotas":{"type":"object","properties":{"session_minute":{"type":["integer","null"],"minimum":0},"navigate":{"type":["integer","null"],"minimum":0},"interact":{"type":["integer","null"],"minimum":0},"wait":{"type":["integer","null"],"minimum":0},"state_capture":{"type":["integer","null"],"minimum":0},"screenshot_capture":{"type":["integer","null"],"minimum":0}}}},"required":["period_start","period_end","tier","totals","quotas"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/usage/series":{"get":{"summary":"Daily-bucketed usage time series for the calling account","tags":["Usage"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":90},"required":false,"name":"days","in":"query"}],"responses":{"200":{"description":"Per-day totals over the trailing window (default 30 days, max 90).","content":{"application/json":{"schema":{"type":"object","properties":{"from_date":{"type":"string"},"to_date":{"type":"string"},"buckets":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"totals":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"required":["date","totals"]}}},"required":["from_date","to_date","buckets"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/team/invites":{"post":{"summary":"Invite an email to join the calling owner’s team","tags":["Team"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInviteRequest"}}}},"responses":{"202":{"description":"Invite sent. The invitee can accept via the email link.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"summary":"List pending invites for the calling owner","tags":["Team"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Pending invites.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TeamInvite"}}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/team/invites/accept":{"post":{"summary":"Accept a pending team invite","tags":["Team"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamAcceptRequest"}}}},"responses":{"200":{"description":"Membership recorded. (Auth-path integration is V-298d; member acts as owner only after that ships.)","content":{"application/json":{"schema":{"type":"object","properties":{"membership":{"$ref":"#/components/schemas/TeamMember"}},"required":["membership"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Invite not found or already used.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Accepting account email does not match invite.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/team/members":{"get":{"summary":"List confirmed team members for the calling owner","tags":["Team"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Team members.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TeamMember"}}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/team/owners":{"get":{"summary":"List owner accounts the caller is a member of (V-326c)","tags":["Team"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Owner accounts the caller is a team member of.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TeamOwner"}}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/team/members/{id}":{"delete":{"summary":"Remove a team member","tags":["Team"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Membership removed."},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Membership not found or owned by a different account.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/health":{"get":{"summary":"Liveness probe","tags":["Meta"],"responses":{"200":{"description":"Server is up.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}}}}},"/v1/admin/accounts/{id}/tier":{"post":{"summary":"Change account tier (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Prefixed account id (acc_<uuid>)"},"required":true,"description":"Prefixed account id (acc_<uuid>)","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"reason":{"type":"string","maxLength":500}},"required":["tier"]}}}},"responses":{"200":{"description":"Updated account row.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^acc_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"email":{"type":"string","format":"email"},"name":{"type":["string","null"]},"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"status":{"type":"string","enum":["active","suspended","deleted"]},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","email","name","tier","status","created_at","updated_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Account not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/accounts/{id}/suspend":{"post":{"summary":"Suspend an account (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","maxLength":500}}}}}},"responses":{"200":{"description":"Account suspended.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^acc_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"email":{"type":"string","format":"email"},"name":{"type":["string","null"]},"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"status":{"type":"string","enum":["active","suspended","deleted"]},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","email","name","tier","status","created_at","updated_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Account not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/accounts/{id}/unsuspend":{"post":{"summary":"Restore a suspended account (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","maxLength":500}}}}}},"responses":{"200":{"description":"Account active.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^acc_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"email":{"type":"string","format":"email"},"name":{"type":["string","null"]},"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"status":{"type":"string","enum":["active","suspended","deleted"]},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","email","name","tier","status","created_at","updated_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Account not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/accounts/{id}/usage":{"get":{"summary":"Usage period summary for any account (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Period summary for the target account.","content":{"application/json":{"schema":{"type":"object","properties":{"period_start":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"period_end":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"totals":{"type":"object","properties":{"session_minute":{"type":"integer","minimum":0},"navigate":{"type":"integer","minimum":0},"interact":{"type":"integer","minimum":0},"wait":{"type":"integer","minimum":0},"state_capture":{"type":"integer","minimum":0},"screenshot_capture":{"type":"integer","minimum":0}}},"quotas":{"type":"object","properties":{"session_minute":{"type":["integer","null"],"minimum":0},"navigate":{"type":["integer","null"],"minimum":0},"interact":{"type":["integer","null"],"minimum":0},"wait":{"type":["integer","null"],"minimum":0},"state_capture":{"type":["integer","null"],"minimum":0},"screenshot_capture":{"type":["integer","null"],"minimum":0}}}},"required":["period_start","period_end","tier","totals","quotas"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Account not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/accounts/{id}/quota-override":{"post":{"summary":"Set a temporary rate-limit override on a bucket (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"bucket_key":{"type":"string","enum":["global","sessions:create"]},"capacity":{"type":"integer","minimum":1,"maximum":1000000},"refill_per_second":{"type":"number","minimum":0.01,"maximum":100000},"duration_seconds":{"type":"integer","minimum":1,"maximum":2592000},"reason":{"type":"string","maxLength":500}},"required":["bucket_key","capacity","refill_per_second","duration_seconds"]}}}},"responses":{"200":{"description":"Override stored. Effective on the next auth-cache miss for the target.","content":{"application/json":{"schema":{"type":"object","properties":{"account_id":{"type":"string"},"bucket_key":{"type":"string"},"capacity":{"type":"integer"},"refill_per_second":{"type":"number"},"reason":{"type":["string","null"]},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["account_id","bucket_key","capacity","refill_per_second","reason","expires_at","created_at","updated_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Account not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Clear a rate-limit override (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["global","sessions:create"]},"required":true,"name":"bucket_key","in":"query"}],"responses":{"204":{"description":"Override cleared."},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No active override for that bucket.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/webhook-deliveries/{id}":{"get":{"summary":"Fetch one webhook delivery (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Prefixed delivery id (wdl_<uuid>)"},"required":true,"description":"Prefixed delivery id (wdl_<uuid>)","name":"id","in":"path"}],"responses":{"200":{"description":"Delivery row.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^wdl_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"webhook_id":{"type":"string","pattern":"^whk_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"event_id":{"type":"string","format":"uuid"},"event_type":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked","test.ping"]},"status":{"type":"string","enum":["pending","in_flight","delivered","failed","dlq"]},"attempts":{"type":"integer","minimum":0},"next_attempt_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_response_status":{"type":["integer","null"]},"last_response_excerpt":{"type":["string","null"]},"last_error":{"type":["string","null"]},"delivered_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","webhook_id","event_id","event_type","status","attempts","next_attempt_at","last_response_status","last_response_excerpt","last_error","delivered_at","created_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Delivery not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/webhook-deliveries/{id}/replay":{"post":{"summary":"Replay a webhook delivery (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Delivery reset to pending; worker will retry.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^wdl_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"webhook_id":{"type":"string","pattern":"^whk_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"event_id":{"type":"string","format":"uuid"},"event_type":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked","test.ping"]},"status":{"type":"string","enum":["pending","in_flight","delivered","failed","dlq"]},"attempts":{"type":"integer","minimum":0},"next_attempt_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_response_status":{"type":["integer","null"]},"last_response_excerpt":{"type":["string","null"]},"last_error":{"type":["string","null"]},"delivered_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","webhook_id","event_id","event_type","status","attempts","next_attempt_at","last_response_status","last_response_excerpt","last_error","delivered_at","created_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Delivery not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/webhook-dlq":{"get":{"summary":"List dead-lettered webhook deliveries across accounts (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"Paginated DLQ list.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^wdl_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"webhook_id":{"type":"string","pattern":"^whk_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"event_id":{"type":"string","format":"uuid"},"event_type":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked","test.ping"]},"status":{"type":"string","enum":["pending","in_flight","delivered","failed","dlq"]},"attempts":{"type":"integer","minimum":0},"next_attempt_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_response_status":{"type":["integer","null"]},"last_response_excerpt":{"type":["string","null"]},"last_error":{"type":["string","null"]},"delivered_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","webhook_id","event_id","event_type","status","attempts","next_attempt_at","last_response_status","last_response_excerpt","last_error","delivered_at","created_at"]}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/webhook-dlq/{id}/requeue":{"post":{"summary":"Requeue a DLQ webhook delivery (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"DLQ entry reset to pending.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^wdl_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"webhook_id":{"type":"string","pattern":"^whk_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"event_id":{"type":"string","format":"uuid"},"event_type":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked","test.ping"]},"status":{"type":"string","enum":["pending","in_flight","delivered","failed","dlq"]},"attempts":{"type":"integer","minimum":0},"next_attempt_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_response_status":{"type":["integer","null"]},"last_response_excerpt":{"type":["string","null"]},"last_error":{"type":["string","null"]},"delivered_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","webhook_id","event_id","event_type","status","attempts","next_attempt_at","last_response_status","last_response_excerpt","last_error","delivered_at","created_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Delivery not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Delivery is not in DLQ — use /webhook-deliveries/:id/replay instead.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/webhook-deliveries/{deliveryId}/replay":{"post":{"summary":"Replay a webhook delivery (V-307; customer self-service)","tags":["Webhooks"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Prefixed delivery id (wdl_<uuid>)"},"required":true,"description":"Prefixed delivery id (wdl_<uuid>)","name":"deliveryId","in":"path"}],"responses":{"200":{"description":"Delivery reset to pending; the worker re-fires within ~30s.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^wdl_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"webhook_id":{"type":"string","pattern":"^whk_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"event_id":{"type":"string","format":"uuid"},"event_type":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked","test.ping"]},"status":{"type":"string","enum":["pending","in_flight","delivered","failed","dlq"]},"attempts":{"type":"integer","minimum":0},"next_attempt_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_response_status":{"type":["integer","null"]},"last_response_excerpt":{"type":["string","null"]},"last_error":{"type":["string","null"]},"delivered_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","webhook_id","event_id","event_type","status","attempts","next_attempt_at","last_response_status","last_response_excerpt","last_error","delivered_at","created_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Delivery not found or not owned by the calling account.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/audit-log":{"get":{"summary":"Query the admin audit log (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"admin_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"target_id","in":"query"},{"schema":{"type":"string","enum":["account.tier_changed","account.suspended","account.unsuspended","webhook_delivery.replayed","webhook_delivery.requeued","rate_limit_override.set","rate_limit_override.cleared","session.destroyed_by_admin","api_key.revoked_by_admin","audit_note.added","refund.recorded","incident.created","incident.updated","incident.resolved","status_subscriber.force_unsubscribed","status_subscriber.purged"]},"required":false,"name":"action","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"required":false,"description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z","name":"from","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"required":false,"description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z","name":"to","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"Paginated audit log entries.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"admin_account_id":{"type":"string"},"admin_key_id":{"type":"string"},"action":{"type":"string","enum":["account.tier_changed","account.suspended","account.unsuspended","webhook_delivery.replayed","webhook_delivery.requeued","rate_limit_override.set","rate_limit_override.cleared","session.destroyed_by_admin","api_key.revoked_by_admin","audit_note.added","refund.recorded","incident.created","incident.updated","incident.resolved","status_subscriber.force_unsubscribed","status_subscriber.purged"]},"target_account_id":{"type":["string","null"]},"target_resource_id":{"type":["string","null"]},"input_payload":{"type":["object","null"],"additionalProperties":{}},"result":{"type":"string"},"ip_address":{"type":["string","null"]},"timestamp":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","admin_account_id","admin_key_id","action","target_account_id","target_resource_id","input_payload","result","ip_address","timestamp"]}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/version":{"get":{"summary":"Build + runtime metadata (public)","tags":["public"],"responses":{"200":{"description":"Server version, git sha, start time, node version.","content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"string"},"git_sha":{"type":"string"},"started_at":{"type":"string"},"node_version":{"type":"string"}},"required":["version","git_sha","started_at","node_version"]}}}}}}},"/v1/admin/validation-schedules":{"get":{"summary":"List continuous-validation schedules (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"All registered validation schedules.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"archetype_id":{"type":"string"},"cadence_seconds":{"type":"integer","exclusiveMinimum":0},"enabled":{"type":"boolean"},"last_run_at":{"type":["string","null"]},"next_run_at":{"type":"string"},"last_run_id":{"type":["string","null"]},"reason":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","archetype_id","cadence_seconds","enabled","last_run_at","next_run_at","last_run_id","reason","created_at","updated_at"]}}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"put":{"summary":"Upsert a validation schedule (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"archetype_id":{"type":"string"},"cadence_seconds":{"type":"integer","minimum":60},"enabled":{"type":"boolean"},"reason":{"type":"string"}},"required":["archetype_id","cadence_seconds"]}}}},"responses":{"200":{"description":"The upserted schedule.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"archetype_id":{"type":"string"},"cadence_seconds":{"type":"integer","exclusiveMinimum":0},"enabled":{"type":"boolean"},"last_run_at":{"type":["string","null"]},"next_run_at":{"type":"string"},"last_run_id":{"type":["string","null"]},"reason":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","archetype_id","cadence_seconds","enabled","last_run_at","next_run_at","last_run_id","reason","created_at","updated_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/validation-schedules/{archetype}":{"delete":{"summary":"Remove a validation schedule (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"responses":{"204":{"description":"Schedule removed."},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/validation-schedules/{archetype}/trigger":{"post":{"summary":"Trigger an immediate validation run (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Run id of the dispatched recapture.","content":{"application/json":{"schema":{"type":"object","properties":{"run_id":{"type":"string"}},"required":["run_id"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/account/me":{"get":{"summary":"Read the calling account (full self-visible state)","tags":["account"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Calling account's full state including tier caps + team memberships.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string","format":"email"},"name":{"type":["string","null"]},"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"status":{"type":"string","enum":["active","suspended","deleted"]},"timezone":{"type":["string","null"]},"slug":{"type":["string","null"]},"region":{"type":["string","null"],"enum":["us","eu","apac"]},"avatar_url":{"type":["string","null"]},"mfa_enrolled":{"type":"boolean"},"concurrent_session_cap":{"type":"integer","minimum":0},"concurrent_session_active":{"type":"integer","minimum":0},"profile_cap":{"type":["integer","null"],"minimum":0},"profile_count":{"type":"integer","minimum":0},"teams":{"type":"array","items":{"type":"object","properties":{"owner_account_id":{"type":"string"},"role":{"type":"string","enum":["admin","member"]},"membership_id":{"type":"string"}},"required":["owner_account_id","role","membership_id"]}}},"required":["id","email","name","tier","status","timezone","slug","region","avatar_url","mfa_enrolled","concurrent_session_cap","concurrent_session_active","profile_cap","profile_count","teams"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"summary":"Partial update of name / timezone / slug / region","tags":["account"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":["string","null"],"minLength":1,"maxLength":120},"timezone":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^[A-Za-z]+(?:\\/[A-Za-z0-9_+-]+)+$"},"slug":{"type":["string","null"],"minLength":3,"maxLength":32,"pattern":"^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$"},"region":{"type":["string","null"],"enum":["us","eu","apac"]}}}}}},"responses":{"200":{"description":"Updated account state.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string","format":"email"},"name":{"type":["string","null"]},"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"status":{"type":"string","enum":["active","suspended","deleted"]},"timezone":{"type":["string","null"]},"slug":{"type":["string","null"]},"region":{"type":["string","null"],"enum":["us","eu","apac"]},"avatar_url":{"type":["string","null"]},"mfa_enrolled":{"type":"boolean"},"concurrent_session_cap":{"type":"integer","minimum":0},"concurrent_session_active":{"type":"integer","minimum":0},"profile_cap":{"type":["integer","null"],"minimum":0},"profile_count":{"type":"integer","minimum":0},"teams":{"type":"array","items":{"type":"object","properties":{"owner_account_id":{"type":"string"},"role":{"type":"string","enum":["admin","member"]},"membership_id":{"type":"string"}},"required":["owner_account_id","role","membership_id"]}}},"required":["id","email","name","tier","status","timezone","slug","region","avatar_url","mfa_enrolled","concurrent_session_cap","concurrent_session_active","profile_cap","profile_count","teams"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Slug already in use by another account.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/account/me/avatar":{"post":{"summary":"Upload (or replace) the calling account avatar (V-352b)","tags":["account"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"content_type":{"type":"string","enum":["image/png","image/jpeg","image/webp"]},"data_base64":{"type":"string","minLength":4,"maxLength":2796207,"pattern":"^[A-Za-z0-9+/=]+$"}},"required":["content_type","data_base64"]}}}},"responses":{"200":{"description":"Avatar stored; presigned read URL returned.","content":{"application/json":{"schema":{"type":"object","properties":{"avatar_url":{"type":["string","null"]},"content_type":{"type":"string","enum":["image/png","image/jpeg","image/webp"]},"bytes":{"type":"integer","minimum":0}},"required":["avatar_url","content_type","bytes"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Avatar payload exceeds the per-route body limit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Avatar storage unavailable in this deploy.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Clear the calling account avatar pointer (V-352b)","tags":["account"],"security":[{"BearerAuth":[]}],"responses":{"204":{"description":"Avatar cleared."},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/account/rate-limits":{"get":{"summary":"Effective rate-limit config for the calling account","tags":["account"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Per-bucket capacity + refill, with override-vs-default source.","content":{"application/json":{"schema":{"type":"object","properties":{"tier":{"type":"string"},"buckets":{"type":"array","items":{"type":"object","properties":{"bucket_key":{"type":"string","enum":["global","sessions:create"]},"capacity":{"type":"integer","exclusiveMinimum":0},"refill_per_second":{"type":"number","exclusiveMinimum":0},"source":{"type":"string","enum":["tier_default","override"]},"override_expires_at":{"type":["string","null"]}},"required":["bucket_key","capacity","refill_per_second","source","override_expires_at"]}}},"required":["tier","buckets"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/account/audit-log":{"get":{"summary":"List the calling account's own audit-log entries","tags":["account"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"action","in":"query"}],"responses":{"200":{"description":"Paginated audit-log entries (newest first).","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"account_id":{"type":"string"},"actor_type":{"type":"string","enum":["customer","system","staff"]},"actor_account_id":{"type":["string","null"]},"actor_key_id":{"type":["string","null"]},"action":{"type":"string"},"target_resource_id":{"type":["string","null"]},"payload":{"type":["object","null"],"additionalProperties":{}},"ip_address":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"timestamp":{"type":"string"}},"required":["id","account_id","actor_type","actor_account_id","actor_key_id","action","target_resource_id","payload","ip_address","user_agent","timestamp"]}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/account/audit-log/export":{"get":{"summary":"Bulk-export the calling account's audit log (GDPR Article 20)","tags":["account"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["csv","json"]},"required":false,"name":"format","in":"query"}],"responses":{"200":{"description":"JSON envelope when format=json (or omitted); text/csv attachment when format=csv. The `x-driftstack-export-truncated` response header signals when the 10,000-row ceiling was hit.","content":{"application/json":{"schema":{"type":"object","properties":{"generated_at":{"type":"string"},"account_id":{"type":"string"},"row_count":{"type":"integer","minimum":0},"truncated":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"account_id":{"type":"string"},"actor_type":{"type":"string","enum":["customer","system","staff"]},"actor_account_id":{"type":["string","null"]},"actor_key_id":{"type":["string","null"]},"action":{"type":"string"},"target_resource_id":{"type":["string","null"]},"payload":{"type":["object","null"],"additionalProperties":{}},"ip_address":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"timestamp":{"type":"string"}},"required":["id","account_id","actor_type","actor_account_id","actor_key_id","action","target_resource_id","payload","ip_address","user_agent","timestamp"]}}},"required":["generated_at","account_id","row_count","truncated","data"]}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/account/email-preferences":{"get":{"summary":"List email notification preferences","tags":["account"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Per-event opt-in state. Defaults to opted-in.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"event_type":{"type":"string","enum":["signup-welcome","session-failed-first","tier-changed","trial-pack-purchased","trial-pack-expired","billing-receipt"]},"opted_in":{"type":"boolean"}},"required":["event_type","opted_in"]}}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"put":{"summary":"Set a single email notification preference","tags":["account"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"event_type":{"type":"string","enum":["signup-welcome","session-failed-first","tier-changed","trial-pack-purchased","trial-pack-expired","billing-receipt"]},"opted_in":{"type":"boolean"}},"required":["event_type","opted_in"]}}}},"responses":{"204":{"description":"Preference updated."},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/rate-limit-overrides":{"get":{"summary":"Cross-account rate-limit override list (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"account_id","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"include_expired","in":"query"}],"responses":{"200":{"description":"Paginated cross-account rate-limit overrides.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"account_id":{"type":"string"},"bucket_key":{"type":"string"},"capacity":{"type":"integer"},"refill_per_second":{"type":"number"},"reason":{"type":["string","null"]},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["account_id","bucket_key","capacity","refill_per_second","reason","expires_at","created_at","updated_at"]}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/api-keys":{"get":{"summary":"Cross-account API key list (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"account_id","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"revoked","in":"query"}],"responses":{"200":{"description":"Paginated cross-account API keys.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^key_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"name":{"type":"string"},"key_prefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","admin","account_owner","driftstack_internal_admin","gui_control"]}},"last_used_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"revoked_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"expires_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","name","key_prefix","scopes","last_used_at","revoked_at","expires_at","created_at"]}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/sessions":{"get":{"summary":"Cross-account session list (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","enum":["creating","ready","busy","destroyed","errored"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"account_id","in":"query"}],"responses":{"200":{"description":"Paginated cross-account sessions.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^ses_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"account_id":{"type":"string","pattern":"^acc_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"api_key_id":{"type":"string","pattern":"^key_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"status":{"type":"string","enum":["creating","ready","busy","destroyed","errored"]},"archetype":{"type":"string","minLength":3,"maxLength":60,"pattern":"^[a-z0-9_]+$"},"purpose":{"type":"string","enum":["production_customer","cumulative_rig_validation","test_domain_probe"]},"label":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":{}},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_state_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"destroyed_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","account_id","api_key_id","status","archetype","purpose","label","metadata","created_at","updated_at","last_state_at","destroyed_at"]}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/overview":{"get":{"summary":"Aggregate counts for the admin panel index page (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Aggregate active/suspended account counts and DLQ depth.","content":{"application/json":{"schema":{"type":"object","properties":{"accounts":{"type":"object","properties":{"active":{"type":"integer","minimum":0},"suspended":{"type":"integer","minimum":0}},"required":["active","suspended"]},"webhooks":{"type":"object","properties":{"dlq_depth":{"type":"integer","minimum":0}},"required":["dlq_depth"]}},"required":["accounts","webhooks"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/accounts":{"get":{"summary":"List accounts with optional filters (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","enum":["active","suspended","deleted"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"tier","in":"query"},{"schema":{"type":"string"},"required":false,"name":"email_contains","in":"query"}],"responses":{"200":{"description":"Cursor-paginated account rows.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^acc_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"email":{"type":"string","format":"email"},"name":{"type":["string","null"]},"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"status":{"type":"string","enum":["active","suspended","deleted"]},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","email","name","tier","status","created_at","updated_at"]}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["data","has_more","next_cursor"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/accounts/{id}":{"get":{"summary":"Get a single account (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Account row.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^acc_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"email":{"type":"string","format":"email"},"name":{"type":["string","null"]},"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"status":{"type":"string","enum":["active","suspended","deleted"]},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","email","name","tier","status","created_at","updated_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Account not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/accounts/{id}/audit-note":{"post":{"summary":"Record a free-form support note on an account (admin; V-281)","tags":["admin"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","minLength":1,"maxLength":2000}},"required":["note"]}}}},"responses":{"200":{"description":"Note recorded.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/accounts/{id}/refund-record":{"post":{"summary":"Record a refund issued out-of-band against the account (admin; V-281)","tags":["admin"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"amount_cents":{"type":"integer","exclusiveMinimum":0},"currency":{"type":"string","minLength":3,"maxLength":3},"reason":{"type":"string","minLength":1,"maxLength":2000},"stripe_refund_id":{"type":"string"}},"required":["amount_cents","currency","reason"]}}}},"responses":{"200":{"description":"Refund recorded for audit. Money movement happens via Stripe dashboard manually per V-280 launch-day runbook.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/api-keys/{id}/revoke":{"post":{"summary":"Force-revoke an API key (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Key revoked. Idempotent.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"API key not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/sessions/{id}/destroy":{"post":{"summary":"Force-destroy an in-flight session (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Session destroyed. Idempotent against already-destroyed sessions.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Session not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/incidents":{"post":{"summary":"Create an incident (admin; V-295)","tags":["admin"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"body":{"type":"string","minLength":1,"maxLength":10000},"severity":{"type":"string","enum":["minor","major","critical"]},"status":{"type":"string","enum":["investigating","identified","monitoring","resolved"]},"started_at":{"type":"string"},"components_affected":{"type":"array","items":{"type":"string"}},"public":{"type":"boolean"}},"required":["title","body","severity"]}}}},"responses":{"200":{"description":"Incident created.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"severity":{"type":"string","enum":["minor","major","critical"]},"status":{"type":"string","enum":["investigating","identified","monitoring","resolved"]},"started_at":{"type":"string"},"resolved_at":{"type":["string","null"]},"components_affected":{"type":"array","items":{"type":"string"}},"public":{"type":"boolean"}},"required":["id","title","body","severity","status","started_at","resolved_at","components_affected","public"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/incidents/{id}":{"get":{"summary":"Get a single incident with its update timeline (admin; V-295)","tags":["admin"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Incident detail (incl. updates timeline).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"severity":{"type":"string","enum":["minor","major","critical"]},"status":{"type":"string","enum":["investigating","identified","monitoring","resolved"]},"started_at":{"type":"string"},"resolved_at":{"type":["string","null"]},"components_affected":{"type":"array","items":{"type":"string"}},"public":{"type":"boolean"}},"required":["id","title","body","severity","status","started_at","resolved_at","components_affected","public"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Incident not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/incidents/{id}/updates":{"post":{"summary":"Append an update to an incident (admin; V-295)","tags":["admin"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":10000},"status":{"type":"string","enum":["investigating","identified","monitoring","resolved"]}},"required":["body"]}}}},"responses":{"200":{"description":"Update appended; incident timeline reflects the new entry.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"severity":{"type":"string","enum":["minor","major","critical"]},"status":{"type":"string","enum":["investigating","identified","monitoring","resolved"]},"started_at":{"type":"string"},"resolved_at":{"type":["string","null"]},"components_affected":{"type":"array","items":{"type":"string"}},"public":{"type":"boolean"}},"required":["id","title","body","severity","status","started_at","resolved_at","components_affected","public"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Incident not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/incidents/{id}/resolve":{"post":{"summary":"Mark an incident resolved (admin; V-295)","tags":["admin"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Incident transitioned to status=resolved + resolved_at set.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"severity":{"type":"string","enum":["minor","major","critical"]},"status":{"type":"string","enum":["investigating","identified","monitoring","resolved"]},"started_at":{"type":"string"},"resolved_at":{"type":["string","null"]},"components_affected":{"type":"array","items":{"type":"string"}},"public":{"type":"boolean"}},"required":["id","title","body","severity","status","started_at","resolved_at","components_affected","public"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Incident not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/status-subscribers":{"get":{"summary":"List status-page subscribers (admin)","tags":["admin"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"boolean"},"required":false,"name":"confirmed","in":"query"}],"responses":{"200":{"description":"Paginated subscribers.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"confirmed":{"type":"boolean"},"created_at":{"type":"string"},"confirmed_at":{"type":["string","null"]}},"required":["id","email","confirmed","created_at","confirmed_at"]}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["data","has_more","next_cursor"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/status-subscribers/{id}/force-unsubscribe":{"post":{"summary":"Force-unsubscribe a status subscriber (admin; abuse / GDPR)","tags":["admin"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Subscriber removed. Idempotent against already-removed entries.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Subscriber not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/account/mfa":{"get":{"summary":"MFA enrollment status for the calling account","tags":["account","mfa"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"enrolled flag + timestamps + remaining recovery-code count.","content":{"application/json":{"schema":{"type":"object","properties":{"enrolled":{"type":"boolean"},"enrolled_at":{"type":["string","null"]},"last_used_at":{"type":["string","null"]},"unused_recovery_codes":{"type":"integer","minimum":0}},"required":["enrolled","enrolled_at","last_used_at","unused_recovery_codes"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Disable MFA. Step-up gated (requires fresh MFA proof).","tags":["account","mfa"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"string","enum":["disable-mfa"]}},"required":["confirm"]}}}},"responses":{"204":{"description":"MFA disabled; recovery codes invalidated."},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/account/mfa/enroll":{"post":{"summary":"Start MFA TOTP enrollment (returns otpauth URI + base32 secret)","tags":["account","mfa"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Pending enrollment row created; secret shown once for QR / manual entry.","content":{"application/json":{"schema":{"type":"object","properties":{"otpauth_uri":{"type":"string"},"secret_base32":{"type":"string"},"algorithm":{"type":"string","enum":["SHA1"]},"digits":{"type":"number","enum":[6]},"period_seconds":{"type":"number","enum":[30]}},"required":["otpauth_uri","secret_base32","algorithm","digits","period_seconds"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Already enrolled — disable first.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/account/mfa/verify":{"post":{"summary":"Confirm enrollment with first 6-digit code; returns 10 single-use recovery codes","tags":["account","mfa"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","pattern":"^\\d{6}$"}},"required":["code"]}}}},"responses":{"200":{"description":"Enrollment activated; recovery codes shown ONCE.","content":{"application/json":{"schema":{"type":"object","properties":{"recovery_codes":{"type":"array","items":{"type":"string"}}},"required":["recovery_codes"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/account/mfa/disable":{"post":{"summary":"POST alias for DELETE /v1/account/mfa. Same step-up gate.","tags":["account","mfa"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"string","enum":["disable-mfa"]}},"required":["confirm"]}}}},"responses":{"204":{"description":"MFA disabled."},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/account/mfa/recovery-codes/regenerate":{"post":{"summary":"Mint 10 fresh recovery codes; old codes invalidated","tags":["account","mfa"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Fresh recovery codes shown ONCE.","content":{"application/json":{"schema":{"type":"object","properties":{"recovery_codes":{"type":"array","items":{"type":"string"}}},"required":["recovery_codes"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/auth/mfa/challenge":{"post":{"summary":"Exchange a login challenge_token for a real session via TOTP / recovery code","tags":["auth","mfa"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"challenge_token":{"type":"string"},"code":{"type":"string","pattern":"^\\d{6}$"},"recovery_code":{"type":"string"}},"required":["challenge_token"]}}}},"responses":{"200":{"description":"Session issued; via discriminator says totp or recovery.","content":{"application/json":{"schema":{"type":"object","properties":{"session":{"type":"object","properties":{"token":{"type":"string"},"expires_at":{"type":"string"},"account_id":{"type":"string"}},"required":["token","expires_at","account_id"]},"via":{"type":"string","enum":["totp","recovery"]}},"required":["session","via"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/auth/mfa/step-up":{"post":{"summary":"Refresh mfa_satisfied_at on the calling web session (no new session issued)","tags":["auth","mfa"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","pattern":"^\\d{6}$"},"recovery_code":{"type":"string"}}}}}},"responses":{"200":{"description":"mfa_satisfied_at advanced to now.","content":{"application/json":{"schema":{"type":"object","properties":{"via":{"type":"string","enum":["totp","recovery"]},"mfa_satisfied_at":{"type":"string"}},"required":["via","mfa_satisfied_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/auth/signup":{"post":{"summary":"Sign up a new account; emits a verification email","tags":["auth"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email","description":"Account email — normalised lowercase server-side"},"password":{"type":"string","minLength":12,"maxLength":128,"description":"Account password — 12-128 chars; no composition rules per NIST 800-63B"},"name":{"type":"string","minLength":1,"maxLength":120}},"required":["email","password"]}}}},"responses":{"200":{"description":"Verification email sent; account is unverified until /v1/auth/verify-email.","content":{"application/json":{"schema":{"type":"object","properties":{"verification_email_expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"debug_token":{"type":"string","description":"Stub email mode only — the plaintext verification token"}},"required":["verification_email_expires_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Email is already registered.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/auth/verify-email":{"post":{"summary":"Consume the email-verification token; issues a web session","tags":["auth"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","minLength":32,"maxLength":256,"pattern":"^[A-Za-z0-9_-]+$","description":"URL-safe single-use auth token; sha256-hashed at rest"}},"required":["token"]}}}},"responses":{"200":{"description":"Email verified; web session issued.","content":{"application/json":{"schema":{"type":"object","properties":{"session":{"type":"object","properties":{"token":{"type":"string"},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"account_id":{"type":"string"}},"required":["token","expires_at","account_id"]}},"required":["session"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/auth/login":{"post":{"summary":"Authenticate with email + password; issues a session OR returns an MFA challenge token","tags":["auth"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email","description":"Account email — normalised lowercase server-side"},"password":{"type":"string","minLength":12,"maxLength":128,"description":"Account password — 12-128 chars; no composition rules per NIST 800-63B"}},"required":["email","password"]}}}},"responses":{"200":{"description":"Discriminated-union: session row when MFA isn't enrolled OR { mfa_required: true, challenge_token, challenge_expires_at } when MFA is. Clients branch on the `mfa_required` literal.","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"session":{"type":"object","properties":{"token":{"type":"string"},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"account_id":{"type":"string"}},"required":["token","expires_at","account_id"]}},"required":["session"]},{"type":"object","properties":{"mfa_required":{"type":"boolean","enum":[true]},"challenge_token":{"type":"string"},"challenge_expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["mfa_required","challenge_token","challenge_expires_at"]}]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/auth/refresh":{"post":{"summary":"Exchange a refresh token for a fresh web-session token","tags":["auth"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","minLength":32,"maxLength":256}},"required":["token"]}}}},"responses":{"200":{"description":"Fresh session issued.","content":{"application/json":{"schema":{"type":"object","properties":{"session":{"type":"object","properties":{"token":{"type":"string"},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"account_id":{"type":"string"}},"required":["token","expires_at","account_id"]}},"required":["session"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/auth/logout":{"post":{"summary":"Revoke a web-session token","tags":["auth"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","minLength":32,"maxLength":256}},"required":["token"]}}}},"responses":{"204":{"description":"Session revoked."},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/billing/checkout-session":{"post":{"summary":"Start a Stripe Checkout session for a tier subscription","tags":["billing"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"billing_period":{"type":"string","enum":["monthly","annual"]},"success_url":{"type":"string","format":"uri"},"cancel_url":{"type":"string","format":"uri"}},"required":["tier","billing_period"]}}}},"responses":{"200":{"description":"Checkout URL + session id; redirect the customer to checkout_url.","content":{"application/json":{"schema":{"type":"object","properties":{"checkout_url":{"type":"string","format":"uri"},"checkout_session_id":{"type":"string"}},"required":["checkout_url","checkout_session_id"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/billing/trial-pack":{"post":{"summary":"Start a Stripe Checkout session for the one-time $2.99 trial pack","tags":["billing"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"success_url":{"type":"string","format":"uri"},"cancel_url":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"Checkout URL + session id.","content":{"application/json":{"schema":{"type":"object","properties":{"checkout_url":{"type":"string","format":"uri"},"checkout_session_id":{"type":"string"}},"required":["checkout_url","checkout_session_id"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/billing/portal-session":{"post":{"summary":"Mint a Stripe Customer Portal one-time URL for subscription self-service","tags":["billing"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Portal URL; short-lived; redirect immediately.","content":{"application/json":{"schema":{"type":"object","properties":{"portal_url":{"type":"string","format":"uri"}},"required":["portal_url"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/billing":{"get":{"summary":"Read the calling account billing state (subscription + trial pack)","tags":["billing"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Subscription row + trial-pack credit/expiry/redemption state.","content":{"application/json":{"schema":{"type":"object","properties":{"subscription":{"type":["object","null"],"properties":{"tier":{"type":"string","enum":["trial_pack","solo_manual","team_manual","agency_manual","api_starter","api_builder","api_scale","enterprise"]},"status":{"type":"string","enum":["incomplete","incomplete_expired","trialing","active","past_due","canceled","unpaid","paused"]},"stripe_subscription_id":{"type":"string"},"current_period_end":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"cancel_at_period_end":{"type":"boolean"},"canceled_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["tier","status","stripe_subscription_id","current_period_end","cancel_at_period_end","canceled_at","created_at","updated_at"]},"trial_pack":{"type":"object","properties":{"active":{"type":"boolean"},"credit_cents_remaining":{"type":["integer","null"]},"expires_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"redeemed":{"type":"boolean"}},"required":["active","credit_cents_remaining","expires_at","redeemed"]}},"required":["subscription","trial_pack"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/auth/magic-link/request":{"post":{"summary":"Request a magic-link email; always 200 to avoid account enumeration","tags":["auth"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email","description":"Account email — normalised lowercase server-side"}},"required":["email"]}}}},"responses":{"200":{"description":"Email accepted; if the address matches an account, a magic-link email is delivered. Response shape never confirms account existence.","content":{"application/json":{"schema":{"type":"object","properties":{"sent":{"type":"boolean","enum":[true]},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"debug_token":{"type":"string"}},"required":["sent","expires_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/auth/magic-link/consume":{"post":{"summary":"Exchange a magic-link token for a fresh web session","tags":["auth"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","minLength":32,"maxLength":256,"pattern":"^[A-Za-z0-9_-]+$","description":"URL-safe single-use auth token; sha256-hashed at rest"}},"required":["token"]}}}},"responses":{"200":{"description":"Session issued.","content":{"application/json":{"schema":{"type":"object","properties":{"session":{"type":"object","properties":{"token":{"type":"string"},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"account_id":{"type":"string"}},"required":["token","expires_at","account_id"]}},"required":["session"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/auth/password-reset/request":{"post":{"summary":"Request a password-reset email; always 200 to avoid account enumeration","tags":["auth"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email","description":"Account email — normalised lowercase server-side"}},"required":["email"]}}}},"responses":{"200":{"description":"Email accepted; if the address matches an account, a reset email is delivered.","content":{"application/json":{"schema":{"type":"object","properties":{"sent":{"type":"boolean","enum":[true]},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"debug_token":{"type":"string"}},"required":["sent","expires_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/auth/password-reset/confirm":{"post":{"summary":"Consume a password-reset token + set a new password; issues a fresh session","tags":["auth"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","minLength":32,"maxLength":256,"pattern":"^[A-Za-z0-9_-]+$","description":"URL-safe single-use auth token; sha256-hashed at rest"},"new_password":{"type":"string","minLength":12,"maxLength":128,"description":"Account password — 12-128 chars; no composition rules per NIST 800-63B"}},"required":["token","new_password"]}}}},"responses":{"200":{"description":"Password updated; web session issued.","content":{"application/json":{"schema":{"type":"object","properties":{"session":{"type":"object","properties":{"token":{"type":"string"},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"account_id":{"type":"string"}},"required":["token","expires_at","account_id"]}},"required":["session"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/auth/cli-authorize/initiate":{"post":{"summary":"Start the CLI/GUI activation flow; returns a code + browser URL","tags":["auth"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"state":{"type":"string","minLength":16,"maxLength":128},"client_label":{"type":"string","minLength":1,"maxLength":120}},"required":["state"]}}}},"responses":{"200":{"description":"Activation code + browser URL the CLI/GUI opens. Code expires after ~5min.","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string"},"browser_url":{"type":"string","format":"uri"},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["code","browser_url","expires_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/auth/cli-authorize/bind":{"post":{"summary":"Web-session-authed: bind the CLI/GUI's code to the calling account; mints an API key","tags":["auth"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","minLength":16,"maxLength":128},"state":{"type":"string","minLength":16,"maxLength":128},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","admin","account_owner","driftstack_internal_admin","gui_control"]},"minItems":1}},"required":["code","state"]}}}},"responses":{"200":{"description":"Code bound; CLI/GUI can now poll exchange for the plaintext key.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"account_id":{"type":"string"},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["ok","account_id","expires_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Code not found or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/auth/cli-authorize/exchange":{"post":{"summary":"Poll for the bound API key plaintext (one-shot delivery)","tags":["auth"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","minLength":16,"maxLength":128},"state":{"type":"string","minLength":16,"maxLength":128}},"required":["code","state"]}}}},"responses":{"200":{"description":"Discriminated-union: { status: pending } / { status: bound, api_key, account_id } / { status: expired }. The bound branch is one-shot — subsequent calls 404.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"status":{"type":"string","enum":["pending"]}},"required":["status"]},{"type":"object","properties":{"status":{"type":"string","enum":["bound"]},"api_key":{"type":"string"},"account_id":{"type":"string"}},"required":["status","api_key","account_id"]},{"type":"object","properties":{"status":{"type":"string","enum":["expired"]}},"required":["status"]}]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Code not found or already consumed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/account/web-sessions":{"get":{"summary":"Active dashboard sign-ins for the calling account","tags":["account"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Active web sessions; current session marked.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"os":{"type":"string"},"browser":{"type":"string"},"last_used_at":{"type":"string"},"expires_at":{"type":"string"},"current":{"type":"boolean"}},"required":["id","os","browser","last_used_at","expires_at","current"]}}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Bulk-revoke every dashboard sign-in except the calling one (?keep=current)","tags":["account"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["current"]},"required":true,"name":"keep","in":"query"}],"responses":{"200":{"description":"Other sessions revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"revoked":{"type":"integer","minimum":0}},"required":["revoked"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/account/web-sessions/{id}":{"delete":{"summary":"Revoke a specific dashboard sign-in by id","tags":["account"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Session revoked."},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/status":{"get":{"summary":"Public service status (overall + per-component); 30s cache","tags":["status"],"responses":{"200":{"description":"Status snapshot with components + recent incidents.","content":{"application/json":{"schema":{"type":"object","properties":{"overall_status":{"type":"string","enum":["operational","degraded","major_outage"]},"components":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string","enum":["operational","degraded","major_outage"]},"last_checked_at":{"type":"string"}},"required":["name","status","last_checked_at"]}},"recent_incidents":{"type":"array","items":{}}},"required":["overall_status","components","recent_incidents"]}}}}}}},"/v1/status/incidents":{"get":{"summary":"Public incidents log","tags":["status"],"responses":{"200":{"description":"Incidents (most recent first).","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}}},"required":["data"]}}}}}}},"/v1/status/sla":{"get":{"summary":"Rolling-window uptime percentage vs SLA target","tags":["status"],"responses":{"200":{"description":"Rolling window + uptime + target.","content":{"application/json":{"schema":{"type":"object","properties":{"window_days":{"type":"integer","minimum":0},"uptime_percent":{"type":"number"},"target_percent":{"type":"number"}},"required":["window_days","uptime_percent","target_percent"]}}}}}}},"/v1/status/subscribe":{"post":{"summary":"Subscribe an email to status notifications (double-opt-in)","tags":["status"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"}},"required":["email"]}}}},"responses":{"200":{"description":"Confirmation email sent (always 200 — no enumeration signal).","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}}}}},"/v1/status/subscribe/confirm":{"post":{"summary":"Confirm a status-subscription email via token","tags":["status"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}},"required":["token"]}}}},"responses":{"200":{"description":"Subscription confirmed.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}}}}},"/v1/status/subscribe/unsubscribe":{"post":{"summary":"Unsubscribe an email from status notifications via token","tags":["status"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}},"required":["token"]}}}},"responses":{"200":{"description":"Unsubscribed.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}}}}},"/v1/legal/documents":{"get":{"summary":"List the legal-document catalog (versions + content_hash)","tags":["legal"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Catalog entries (no document body — body served on the marketing site).","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"document_key":{"type":"string"},"title":{"type":"string"},"version":{"type":"string"},"effective_date":{"type":"string"},"content_hash":{"type":"string"},"source_path":{"type":"string"},"byte_size":{"type":"integer","minimum":0}},"required":["document_key","title","version","effective_date","content_hash","source_path","byte_size"]}}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/legal/required":{"get":{"summary":"List documents the calling account must accept (or re-accept)","tags":["legal"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Required acceptances; each entry includes reason + last accepted version.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"document_key":{"type":"string"},"current_version":{"type":"string"},"content_hash":{"type":"string"},"reason":{"type":"string"},"last_accepted_version":{"type":["string","null"]}},"required":["document_key","current_version","content_hash","reason","last_accepted_version"]}}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/legal/accept":{"post":{"summary":"Record acceptance of a (document, version, content_hash) tuple","tags":["legal"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"document_key":{"type":"string","minLength":1,"maxLength":64},"version":{"type":"string","minLength":1,"maxLength":64},"content_hash":{"type":"string","pattern":"^[0-9a-f]{64}$"}},"required":["document_key","version","content_hash"]}}}},"responses":{"201":{"description":"Acceptance recorded.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"account_id":{"type":"string"},"document_key":{"type":"string"},"version":{"type":"string"},"content_hash":{"type":"string"},"accepted_at":{"type":"string"}},"required":["id","account_id","document_key","version","content_hash","accepted_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Document version changed since fetch — re-fetch + retry.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/webhooks":{"post":{"summary":"Create a webhook endpoint","tags":["webhooks"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked"]},"minItems":1,"maxItems":10},"description":{"type":"string","maxLength":200}},"required":["url","events"]}}}},"responses":{"200":{"description":"Created endpoint; plaintext signing secret returned ONCE.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^whk_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"url":{"type":"string","format":"uri"},"secret_prefix":{"type":"string"},"prev_secret_prefix":{"type":["string","null"]},"rotation_grace_expires_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"events":{"type":"array","items":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked","test.ping"]}},"description":{"type":["string","null"]},"active":{"type":"boolean"},"consecutive_failures":{"type":"integer","minimum":0},"last_success_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_failure_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"disabled_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"delivery_counts":{"type":"object","properties":{"delivered":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"dlq":{"type":"integer","minimum":0}},"required":["delivered","failed","dlq"]},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"secret":{"type":"string","description":"Plaintext signing secret. Returned ONCE; not retrievable later."}},"required":["id","url","secret_prefix","prev_secret_prefix","rotation_grace_expires_at","events","description","active","consecutive_failures","last_success_at","last_failure_at","disabled_at","delivery_counts","created_at","secret"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"summary":"List webhook endpoints for the calling account","tags":["webhooks"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Endpoint list (no plaintext).","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^whk_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"url":{"type":"string","format":"uri"},"secret_prefix":{"type":"string"},"prev_secret_prefix":{"type":["string","null"]},"rotation_grace_expires_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"events":{"type":"array","items":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked","test.ping"]}},"description":{"type":["string","null"]},"active":{"type":"boolean"},"consecutive_failures":{"type":"integer","minimum":0},"last_success_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_failure_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"disabled_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"delivery_counts":{"type":"object","properties":{"delivered":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"dlq":{"type":"integer","minimum":0}},"required":["delivered","failed","dlq"]},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","url","secret_prefix","prev_secret_prefix","rotation_grace_expires_at","events","description","active","consecutive_failures","last_success_at","last_failure_at","disabled_at","delivery_counts","created_at"]}}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/webhooks/{id}":{"get":{"summary":"Get a single webhook endpoint","tags":["webhooks"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Endpoint.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^whk_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"url":{"type":"string","format":"uri"},"secret_prefix":{"type":"string"},"prev_secret_prefix":{"type":["string","null"]},"rotation_grace_expires_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"events":{"type":"array","items":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked","test.ping"]}},"description":{"type":["string","null"]},"active":{"type":"boolean"},"consecutive_failures":{"type":"integer","minimum":0},"last_success_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_failure_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"disabled_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"delivery_counts":{"type":"object","properties":{"delivered":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"dlq":{"type":"integer","minimum":0}},"required":["delivered","failed","dlq"]},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","url","secret_prefix","prev_secret_prefix","rotation_grace_expires_at","events","description","active","consecutive_failures","last_success_at","last_failure_at","disabled_at","delivery_counts","created_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"summary":"Partial update of a webhook endpoint (url / events / description / active)","tags":["webhooks"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked"]},"minItems":1,"maxItems":10},"description":{"type":["string","null"],"maxLength":200},"active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated endpoint.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^whk_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"url":{"type":"string","format":"uri"},"secret_prefix":{"type":"string"},"prev_secret_prefix":{"type":["string","null"]},"rotation_grace_expires_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"events":{"type":"array","items":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked","test.ping"]}},"description":{"type":["string","null"]},"active":{"type":"boolean"},"consecutive_failures":{"type":"integer","minimum":0},"last_success_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_failure_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"disabled_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"delivery_counts":{"type":"object","properties":{"delivered":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"dlq":{"type":"integer","minimum":0}},"required":["delivered","failed","dlq"]},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","url","secret_prefix","prev_secret_prefix","rotation_grace_expires_at","events","description","active","consecutive_failures","last_success_at","last_failure_at","disabled_at","delivery_counts","created_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Disable (soft-delete) a webhook endpoint. Idempotent.","tags":["webhooks"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Endpoint disabled."},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/webhooks/{id}/deliveries":{"get":{"summary":"List delivery attempts for a webhook endpoint","tags":["webhooks"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","enum":["pending","in_flight","delivered","failed","dlq"]},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"Paginated delivery list with optional ?status= filter.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^wdl_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"webhook_id":{"type":"string","pattern":"^whk_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"event_id":{"type":"string","format":"uuid"},"event_type":{"type":"string","enum":["session.completed","session.failed","quota.warning_80pct","quota.exceeded","api_key.revoked","test.ping"]},"status":{"type":"string","enum":["pending","in_flight","delivered","failed","dlq"]},"attempts":{"type":"integer","minimum":0},"next_attempt_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"last_response_status":{"type":["integer","null"]},"last_response_excerpt":{"type":["string","null"]},"last_error":{"type":["string","null"]},"delivered_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","webhook_id","event_id","event_type","status","attempts","next_attempt_at","last_response_status","last_response_excerpt","last_error","delivered_at","created_at"]}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["data","has_more","next_cursor"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/webhooks/{id}/test":{"post":{"summary":"Enqueue a synthetic test.ping delivery (bypass subscription)","tags":["webhooks"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"202":{"description":"Test delivery enqueued.","content":{"application/json":{"schema":{"type":"object","properties":{"delivery_id":{"type":"string"},"event_id":{"type":"string"},"event_type":{"type":"string","enum":["test.ping"]}},"required":["delivery_id","event_id","event_type"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/webhooks/{id}/rotate-secret":{"post":{"summary":"Rotate the signing secret with a 24h grace (worker dual-signs during grace)","tags":["webhooks"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Fresh plaintext shown ONCE; prev secret stays valid for 24h.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"secret":{"type":"string"},"secret_prefix":{"type":"string"},"prev_secret_prefix":{"type":"string"},"grace_expires_at":{"type":"string"}},"required":["id","secret","secret_prefix","prev_secret_prefix","grace_expires_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Endpoint is disabled; cannot rotate.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/profiles":{"post":{"summary":"Create a profile","tags":["profiles"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9 _.-]{0,118}[a-zA-Z0-9]$|^[a-zA-Z0-9]$"},"archetype":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":2048}},"required":["name"]}}}},"responses":{"200":{"description":"Created profile.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^prof_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"name":{"type":"string"},"archetype":{"type":"string"},"description":{"type":["string","null"]},"last_used_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","name","archetype","description","last_used_at","created_at","updated_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"summary":"List profiles for the calling account","tags":["profiles"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"Paginated profile list.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^prof_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"name":{"type":"string"},"archetype":{"type":"string"},"description":{"type":["string","null"]},"last_used_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","name","archetype","description","last_used_at","created_at","updated_at"]}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["data","has_more","next_cursor"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/profiles/{id}":{"get":{"summary":"Get a single profile","tags":["profiles"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Profile.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^prof_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"name":{"type":"string"},"archetype":{"type":"string"},"description":{"type":["string","null"]},"last_used_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","name","archetype","description","last_used_at","created_at","updated_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"summary":"Partial update of a profile (name / description)","tags":["profiles"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9 _.-]{0,118}[a-zA-Z0-9]$|^[a-zA-Z0-9]$"},"description":{"type":["string","null"],"maxLength":2048}}}}}},"responses":{"200":{"description":"Updated profile.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^prof_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"name":{"type":"string"},"archetype":{"type":"string"},"description":{"type":["string","null"]},"last_used_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp with timezone offset, e.g. 2026-05-02T09:15:00Z"}},"required":["id","name","archetype","description","last_used_at","created_at","updated_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Delete a profile (storage state wiped; idempotent)","tags":["profiles"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Profile deleted."},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/profiles/{id}/clone":{"post":{"summary":"Duplicate an existing profile metadata row with an auto-derived \"(copy)\" name","tags":["profiles"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}}}}}},"responses":{"200":{"description":"Cloned profile.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"archetype":{"type":"string"},"description":{"type":["string","null"]},"last_used_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","archetype","description","last_used_at","created_at","updated_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/profiles/{id}/snapshots":{"post":{"summary":"Capture an immutable point-in-time snapshot of the profile","tags":["profiles","snapshots"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":2048}},"required":["label"]}}}},"responses":{"200":{"description":"Snapshot captured.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"parent_profile_id":{"type":["string","null"]},"label":{"type":"string"},"description":{"type":["string","null"]},"parent_archetype":{"type":"string"},"parent_name":{"type":"string"},"captured_at":{"type":"string"},"created_at":{"type":"string"}},"required":["id","parent_profile_id","label","description","parent_archetype","parent_name","captured_at","created_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"summary":"List a profile's snapshots, newest-first","tags":["profiles","snapshots"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"Snapshots for this profile.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"parent_profile_id":{"type":["string","null"]},"label":{"type":"string"},"description":{"type":["string","null"]},"parent_archetype":{"type":"string"},"parent_name":{"type":"string"},"captured_at":{"type":"string"},"created_at":{"type":"string"}},"required":["id","parent_profile_id","label","description","parent_archetype","parent_name","captured_at","created_at"]}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["data","has_more","next_cursor"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/profile-snapshots":{"get":{"summary":"List every snapshot owned by the calling account (cross-profile)","tags":["snapshots"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"Snapshots across all profiles.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"parent_profile_id":{"type":["string","null"]},"label":{"type":"string"},"description":{"type":["string","null"]},"parent_archetype":{"type":"string"},"parent_name":{"type":"string"},"captured_at":{"type":"string"},"created_at":{"type":"string"}},"required":["id","parent_profile_id","label","description","parent_archetype","parent_name","captured_at","created_at"]}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["data","has_more","next_cursor"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/profile-snapshots/{id}":{"get":{"summary":"Single snapshot by id","tags":["snapshots"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Snapshot.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"parent_profile_id":{"type":["string","null"]},"label":{"type":"string"},"description":{"type":["string","null"]},"parent_archetype":{"type":"string"},"parent_name":{"type":"string"},"captured_at":{"type":"string"},"created_at":{"type":"string"}},"required":["id","parent_profile_id","label","description","parent_archetype","parent_name","captured_at","created_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"summary":"Hard-delete a snapshot","tags":["snapshots"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Snapshot deleted."},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/profile-snapshots/{id}/restore":{"post":{"summary":"Create a new profile from a snapshot (tier-cap + name-conflict checked)","tags":["snapshots","profiles"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}}}},"responses":{"200":{"description":"New profile created from snapshot.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"archetype":{"type":"string"},"description":{"type":["string","null"]},"last_used_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","archetype","description","last_used_at","created_at","updated_at"]}}}},"400":{"description":"Validation failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Authentication failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Caller not permitted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit or concurrency limit hit.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}},"webhooks":{}}