{"components":{"schemas":{"AcceptInvitationRequest":{"properties":{"full_name":{"anyOf":[{"maxLength":255,"minLength":1,"type":"string"},{"type":"null"}],"title":"Full Name"},"password":{"anyOf":[{"maxLength":200,"minLength":8,"type":"string"},{"type":"null"}],"title":"Password"},"token":{"maxLength":512,"minLength":16,"title":"Token","type":"string"}},"required":["token"],"title":"AcceptInvitationRequest","type":"object"},"BillingProfileIn":{"description":"The addressee for receipts, and the tax registration to print on them.","properties":{"address_line1":{"default":"","maxLength":200,"title":"Address Line1","type":"string"},"address_line2":{"default":"","maxLength":200,"title":"Address Line2","type":"string"},"billing_email":{"default":"","maxLength":320,"title":"Billing Email","type":"string"},"city":{"default":"","maxLength":120,"title":"City","type":"string"},"country_code":{"default":"","maxLength":2,"title":"Country Code","type":"string"},"legal_name":{"default":"","maxLength":200,"title":"Legal Name","type":"string"},"postal_code":{"default":"","maxLength":24,"title":"Postal Code","type":"string"},"state_code":{"default":"","maxLength":8,"title":"State Code","type":"string"},"tax_id":{"default":"","maxLength":64,"title":"Tax Id","type":"string"},"tax_id_type":{"default":"","maxLength":16,"title":"Tax Id Type","type":"string"}},"title":"BillingProfileIn","type":"object"},"Body_import_archive_api_archive_import_post":{"properties":{"file":{"contentMediaType":"application/octet-stream","description":"A chat archive exported from here","title":"File","type":"string"}},"required":["file"],"title":"Body_import_archive_api_archive_import_post","type":"object"},"Body_upload_avatar_api_bots__bot_id__theme_avatar_post":{"properties":{"file":{"contentMediaType":"application/octet-stream","title":"File","type":"string"}},"required":["file"],"title":"Body_upload_avatar_api_bots__bot_id__theme_avatar_post","type":"object"},"Body_upload_document_api_bots__bot_id__knowledge_upload_post":{"properties":{"file":{"contentMediaType":"application/octet-stream","title":"File","type":"string"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"}},"required":["file"],"title":"Body_upload_document_api_bots__bot_id__knowledge_upload_post","type":"object"},"BookRequest":{"properties":{"attendee_email":{"anyOf":[{"format":"email","type":"string"},{"type":"null"}],"title":"Attendee Email"},"attendee_name":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"title":"Attendee Name"},"description":{"anyOf":[{"maxLength":5000,"type":"string"},{"type":"null"}],"title":"Description"},"start":{"format":"date-time","title":"Start","type":"string"},"summary":{"maxLength":500,"minLength":1,"title":"Summary","type":"string"}},"required":["start","summary"],"title":"BookRequest","type":"object"},"BotBlueprint":{"description":"The generated configuration, before it becomes a bot.","properties":{"contact_fields_config":{"items":{},"title":"Contact Fields Config","type":"array"},"description":{"title":"Description","type":"string"},"directory_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Directory Config"},"fallback_message":{"title":"Fallback Message","type":"string"},"industry":{"title":"Industry","type":"string"},"language":{"title":"Language","type":"string"},"lead_capture_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Lead Capture Config"},"name":{"title":"Name","type":"string"},"starter_questions":{"items":{"type":"string"},"title":"Starter Questions","type":"array"},"strict_kb_mode":{"title":"Strict Kb Mode","type":"boolean"},"suggested_kb_topics":{"items":{"type":"string"},"title":"Suggested Kb Topics","type":"array"},"system_prompt":{"title":"System Prompt","type":"string"},"temperature":{"title":"Temperature","type":"number"},"welcome_message":{"title":"Welcome Message","type":"string"},"widget_theme":{"additionalProperties":true,"title":"Widget Theme","type":"object"}},"required":["name","description","industry","system_prompt","welcome_message","starter_questions","fallback_message","language","temperature","strict_kb_mode","lead_capture_config","contact_fields_config","directory_config","widget_theme","suggested_kb_topics"],"title":"BotBlueprint","type":"object"},"BotCreate":{"properties":{"allowed_domains":{"anyOf":[{"items":{"type":"string"},"maxItems":50,"type":"array"},{"type":"null"}],"title":"Allowed Domains"},"api_key":{"anyOf":[{"maxLength":500,"type":"string"},{"type":"null"}],"title":"Api Key"},"contact_fields_config":{"items":{"$ref":"#/components/schemas/ContactFieldDef"},"maxItems":20,"title":"Contact Fields Config","type":"array"},"custom_endpoint_config":{"anyOf":[{"$ref":"#/components/schemas/CustomEndpointConfig"},{"type":"null"}]},"description":{"anyOf":[{"maxLength":2000,"type":"string"},{"type":"null"}],"title":"Description"},"directory_config":{"anyOf":[{"$ref":"#/components/schemas/DirectoryConfig"},{"type":"null"}]},"fallback_message":{"anyOf":[{"maxLength":1000,"type":"string"},{"type":"null"}],"title":"Fallback Message"},"handoff_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Handoff Config"},"handoff_enabled":{"default":false,"title":"Handoff Enabled","type":"boolean"},"is_public":{"default":true,"title":"Is Public","type":"boolean"},"language":{"default":"auto","maxLength":16,"title":"Language","type":"string"},"lead_capture_config":{"anyOf":[{"$ref":"#/components/schemas/LeadCaptureConfig"},{"type":"null"}]},"llm_provider":{"$ref":"#/components/schemas/LLMProviderType","default":"platform"},"max_tokens":{"default":1024,"maximum":32768,"minimum":64,"title":"Max Tokens","type":"integer"},"model":{"anyOf":[{"maxLength":128,"type":"string"},{"type":"null"}],"title":"Model"},"monthly_message_cap":{"anyOf":[{"minimum":0,"type":"integer"},{"type":"null"}],"title":"Monthly Message Cap"},"name":{"maxLength":255,"minLength":1,"title":"Name","type":"string"},"rate_limit_per_minute":{"default":30,"maximum":1000,"minimum":1,"title":"Rate Limit Per Minute","type":"integer"},"starter_questions":{"items":{"type":"string"},"maxItems":6,"title":"Starter Questions","type":"array"},"strict_kb_mode":{"default":false,"title":"Strict Kb Mode","type":"boolean"},"system_prompt":{"anyOf":[{"maxLength":20000,"type":"string"},{"type":"null"}],"title":"System Prompt"},"temperature":{"default":0.7,"maximum":2,"minimum":0,"title":"Temperature","type":"number"},"thinking_budget_tokens":{"default":2048,"maximum":32000,"minimum":1024,"title":"Thinking Budget Tokens","type":"integer"},"thinking_enabled":{"default":false,"title":"Thinking Enabled","type":"boolean"},"welcome_message":{"anyOf":[{"maxLength":1000,"type":"string"},{"type":"null"}],"title":"Welcome Message"},"widget_theme":{"$ref":"#/components/schemas/WidgetTheme"}},"required":["name"],"title":"BotCreate","type":"object"},"BotGenerateRequest":{"description":"One-prompt bot creation.","properties":{"activate":{"default":false,"title":"Activate","type":"boolean"},"description":{"description":"What the business does, who it serves, and what the bot should do.","maxLength":4000,"minLength":10,"title":"Description","type":"string"},"import_website":{"default":true,"title":"Import Website","type":"boolean"},"website_url":{"anyOf":[{"maxLength":1000,"type":"string"},{"type":"null"}],"description":"Optional. Read to match tone and seed the knowledge base.","title":"Website Url"}},"required":["description"],"title":"BotGenerateRequest","type":"object"},"BotGenerateResponse":{"properties":{"blueprint":{"$ref":"#/components/schemas/BotBlueprint"},"bot":{"anyOf":[{"$ref":"#/components/schemas/BotRead"},{"type":"null"}]},"embed_snippet":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Embed Snippet"},"import_job_queued":{"default":false,"title":"Import Job Queued","type":"boolean"}},"required":["blueprint"],"title":"BotGenerateResponse","type":"object"},"BotRead":{"properties":{"allowed_domains":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allowed Domains"},"contact_fields_config":{"items":{},"title":"Contact Fields Config","type":"array"},"created_at":{"format":"date-time","title":"Created At","type":"string"},"custom_endpoint_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Custom Endpoint Config"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"directory_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Directory Config"},"fallback_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fallback Message"},"handoff_enabled":{"title":"Handoff Enabled","type":"boolean"},"has_api_key":{"default":false,"title":"Has Api Key","type":"boolean"},"id":{"title":"Id","type":"string"},"indexed_chunk_count":{"title":"Indexed Chunk Count","type":"integer"},"is_public":{"title":"Is Public","type":"boolean"},"language":{"title":"Language","type":"string"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"lead_capture_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Lead Capture Config"},"llm_provider":{"$ref":"#/components/schemas/LLMProviderType"},"max_tokens":{"title":"Max Tokens","type":"integer"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"monthly_message_cap":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Monthly Message Cap"},"name":{"title":"Name","type":"string"},"org_id":{"title":"Org Id","type":"string"},"public_key":{"title":"Public Key","type":"string"},"rate_limit_per_minute":{"title":"Rate Limit Per Minute","type":"integer"},"starter_questions":{"items":{"type":"string"},"title":"Starter Questions","type":"array"},"status":{"$ref":"#/components/schemas/BotStatus"},"strict_kb_mode":{"title":"Strict Kb Mode","type":"boolean"},"system_prompt":{"title":"System Prompt","type":"string"},"temperature":{"title":"Temperature","type":"number"},"thinking_enabled":{"title":"Thinking Enabled","type":"boolean"},"total_conversations":{"title":"Total Conversations","type":"integer"},"total_messages":{"title":"Total Messages","type":"integer"},"updated_at":{"format":"date-time","title":"Updated At","type":"string"},"welcome_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Welcome Message"},"widget_theme":{"additionalProperties":true,"title":"Widget Theme","type":"object"}},"required":["id","org_id","name","description","status","public_key","llm_provider","model","system_prompt","temperature","max_tokens","thinking_enabled","welcome_message","starter_questions","fallback_message","strict_kb_mode","language","lead_capture_config","contact_fields_config","directory_config","widget_theme","allowed_domains","is_public","rate_limit_per_minute","monthly_message_cap","handoff_enabled","last_error","total_conversations","total_messages","indexed_chunk_count","created_at","updated_at"],"title":"BotRead","type":"object"},"BotStatus":{"enum":["draft","active","paused","archived"],"title":"BotStatus","type":"string"},"BotUpdate":{"description":"Every field optional - PATCH semantics. Only keys present in the request\nbody are applied, so a client can update one field without needing to\nround-trip the whole object and risk clobbering a concurrent edit.","properties":{"allowed_domains":{"anyOf":[{"items":{"type":"string"},"maxItems":50,"type":"array"},{"type":"null"}],"title":"Allowed Domains"},"api_key":{"anyOf":[{"maxLength":500,"type":"string"},{"type":"null"}],"title":"Api Key"},"contact_fields_config":{"anyOf":[{"items":{"$ref":"#/components/schemas/ContactFieldDef"},"maxItems":20,"type":"array"},{"type":"null"}],"title":"Contact Fields Config"},"custom_endpoint_config":{"anyOf":[{"$ref":"#/components/schemas/CustomEndpointConfig"},{"type":"null"}]},"description":{"anyOf":[{"maxLength":2000,"type":"string"},{"type":"null"}],"title":"Description"},"directory_config":{"anyOf":[{"$ref":"#/components/schemas/DirectoryConfig"},{"type":"null"}]},"fallback_message":{"anyOf":[{"maxLength":1000,"type":"string"},{"type":"null"}],"title":"Fallback Message"},"handoff_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Handoff Config"},"handoff_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Handoff Enabled"},"is_public":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Public"},"language":{"anyOf":[{"maxLength":16,"type":"string"},{"type":"null"}],"title":"Language"},"lead_capture_config":{"anyOf":[{"$ref":"#/components/schemas/LeadCaptureConfig"},{"type":"null"}]},"llm_provider":{"anyOf":[{"$ref":"#/components/schemas/LLMProviderType"},{"type":"null"}]},"max_tokens":{"anyOf":[{"maximum":32768,"minimum":64,"type":"integer"},{"type":"null"}],"title":"Max Tokens"},"model":{"anyOf":[{"maxLength":128,"type":"string"},{"type":"null"}],"title":"Model"},"monthly_message_cap":{"anyOf":[{"minimum":0,"type":"integer"},{"type":"null"}],"title":"Monthly Message Cap"},"name":{"anyOf":[{"maxLength":255,"minLength":1,"type":"string"},{"type":"null"}],"title":"Name"},"rate_limit_per_minute":{"anyOf":[{"maximum":1000,"minimum":1,"type":"integer"},{"type":"null"}],"title":"Rate Limit Per Minute"},"starter_questions":{"anyOf":[{"items":{"type":"string"},"maxItems":6,"type":"array"},{"type":"null"}],"title":"Starter Questions"},"status":{"anyOf":[{"$ref":"#/components/schemas/BotStatus"},{"type":"null"}]},"strict_kb_mode":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Strict Kb Mode"},"system_prompt":{"anyOf":[{"maxLength":20000,"type":"string"},{"type":"null"}],"title":"System Prompt"},"temperature":{"anyOf":[{"maximum":2,"minimum":0,"type":"number"},{"type":"null"}],"title":"Temperature"},"thinking_budget_tokens":{"anyOf":[{"maximum":32000,"minimum":1024,"type":"integer"},{"type":"null"}],"title":"Thinking Budget Tokens"},"thinking_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Thinking Enabled"},"welcome_message":{"anyOf":[{"maxLength":1000,"type":"string"},{"type":"null"}],"title":"Welcome Message"},"widget_theme":{"anyOf":[{"$ref":"#/components/schemas/WidgetTheme"},{"type":"null"}]}},"title":"BotUpdate","type":"object"},"BotVersionRead":{"properties":{"created_at":{"format":"date-time","title":"Created At","type":"string"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"snapshot":{"additionalProperties":true,"title":"Snapshot","type":"object"},"version":{"title":"Version","type":"integer"}},"required":["version","note","snapshot","created_at"],"title":"BotVersionRead","type":"object"},"BulkConversationUpdate":{"description":"A batch action over conversations the caller already has ids for.\n\nCapped at 200. That is comfortably inside a request at today's row sizes,\nand the point where it would not be is the point where the right answer is\na queued job rather than a longer timeout - so the cap is a design decision\nrather than a guess, and it fails loudly instead of timing out.","properties":{"action":{"enum":["resolve","reopen","delete"],"title":"Action","type":"string"},"ids":{"items":{"type":"string"},"maxItems":200,"minItems":1,"title":"Ids","type":"array"}},"required":["ids","action"],"title":"BulkConversationUpdate","type":"object"},"BulkOutcome":{"description":"One item's result inside a bulk response.\n\nA bulk endpoint that returns `200 OK` after partially failing is worse than\none that does not exist, because the operator believes it worked and finds\nout later from a customer. Every item reports for itself.","properties":{"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"id":{"title":"Id","type":"string"},"ok":{"title":"Ok","type":"boolean"}},"required":["id","ok"],"title":"BulkOutcome","type":"object"},"BulkResponse":{"properties":{"failed":{"title":"Failed","type":"integer"},"results":{"items":{"$ref":"#/components/schemas/BulkOutcome"},"title":"Results","type":"array"},"succeeded":{"title":"Succeeded","type":"integer"}},"required":["results","succeeded","failed"],"title":"BulkResponse","type":"object"},"Category":{"description":"A kind of lifecycle email, and the unit a person can turn off.","enum":["leads","handoff","content","usage","health","digest","product","bookings"],"title":"Category","type":"string"},"ChangePasswordRequest":{"properties":{"current_password":{"maxLength":200,"minLength":1,"title":"Current Password","type":"string"},"new_password":{"maxLength":200,"minLength":8,"title":"New Password","type":"string"}},"required":["current_password","new_password"],"title":"ChangePasswordRequest","type":"object"},"CheckoutRequest":{"description":"What to buy. Notably absent: any price, and any product id.","properties":{"quantity":{"default":1,"maximum":100,"minimum":1,"title":"Quantity","type":"integer"},"tier":{"description":"One of the purchasable tiers, or 'topup'","title":"Tier","type":"string"}},"required":["tier"],"title":"CheckoutRequest","type":"object"},"ConnectResponse":{"properties":{"authorization_url":{"title":"Authorization Url","type":"string"},"provider":{"title":"Provider","type":"string"}},"required":["authorization_url","provider"],"title":"ConnectResponse","type":"object"},"ConnectionSettings":{"properties":{"booking_calendar_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Booking Calendar Id"},"buffer_minutes":{"anyOf":[{"maximum":240,"minimum":0,"type":"integer"},{"type":"null"}],"title":"Buffer Minutes"},"business_close_hour":{"anyOf":[{"maximum":24,"minimum":1,"type":"integer"},{"type":"null"}],"title":"Business Close Hour"},"business_open_hour":{"anyOf":[{"maximum":23,"minimum":0,"type":"integer"},{"type":"null"}],"title":"Business Open Hour"},"calendar_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Calendar Ids"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"slot_minutes":{"anyOf":[{"maximum":480,"minimum":5,"type":"integer"},{"type":"null"}],"title":"Slot Minutes"},"timezone":{"anyOf":[{"maxLength":64,"type":"string"},{"type":"null"}],"title":"Timezone"},"weekdays_only":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Weekdays Only"}},"title":"ConnectionSettings","type":"object"},"ContactFieldDef":{"description":"A field the model extracts from free conversation.","properties":{"key":{"maxLength":40,"minLength":1,"pattern":"^[a-z][a-z0-9_]*$","title":"Key","type":"string"},"label":{"maxLength":100,"minLength":1,"title":"Label","type":"string"},"options":{"anyOf":[{"items":{"type":"string"},"maxItems":30,"type":"array"},{"type":"null"}],"title":"Options"},"type":{"default":"text","enum":["text","email","phone","select","number"],"title":"Type","type":"string"}},"required":["key","label"],"title":"ContactFieldDef","type":"object"},"ContactRead":{"properties":{"conversation_count":{"default":0,"title":"Conversation Count","type":"integer"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"custom_fields":{"additionalProperties":true,"title":"Custom Fields","type":"object"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"first_seen_at":{"format":"date-time","title":"First Seen At","type":"string"},"id":{"title":"Id","type":"string"},"is_lead":{"default":false,"title":"Is Lead","type":"boolean"},"last_seen_at":{"format":"date-time","title":"Last Seen At","type":"string"},"message_count":{"default":0,"title":"Message Count","type":"integer"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"tags":{"items":{},"title":"Tags","type":"array"},"visitor_id":{"title":"Visitor Id","type":"string"}},"required":["id","visitor_id","first_seen_at","last_seen_at"],"title":"ContactRead","type":"object"},"ConversationDetail":{"properties":{"consent":{"default":"unknown","title":"Consent","type":"string"},"contact_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Email"},"contact_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Id"},"contact_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Name"},"contact_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Phone"},"custom_fields":{"additionalProperties":true,"title":"Custom Fields","type":"object"},"ended_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Ended At"},"id":{"title":"Id","type":"string"},"is_lead":{"default":false,"title":"Is Lead","type":"boolean"},"last_message_at":{"format":"date-time","title":"Last Message At","type":"string"},"message_count":{"default":0,"title":"Message Count","type":"integer"},"messages":{"items":{"$ref":"#/components/schemas/MessageRead"},"title":"Messages","type":"array"},"page_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Page Url"},"rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rating"},"referrer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Referrer"},"resolved":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Resolved"},"sentiment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sentiment"},"started_at":{"format":"date-time","title":"Started At","type":"string"},"status":{"title":"Status","type":"string"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"total_cost_usd":{"default":0,"title":"Total Cost Usd","type":"number"},"total_input_tokens":{"default":0,"title":"Total Input Tokens","type":"integer"},"total_output_tokens":{"default":0,"title":"Total Output Tokens","type":"integer"},"visitor_id":{"title":"Visitor Id","type":"string"}},"required":["id","visitor_id","status","started_at","last_message_at"],"title":"ConversationDetail","type":"object"},"ConversationRead":{"properties":{"consent":{"default":"unknown","title":"Consent","type":"string"},"contact_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Email"},"contact_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Id"},"contact_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Name"},"contact_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Phone"},"custom_fields":{"additionalProperties":true,"title":"Custom Fields","type":"object"},"ended_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Ended At"},"id":{"title":"Id","type":"string"},"is_lead":{"default":false,"title":"Is Lead","type":"boolean"},"last_message_at":{"format":"date-time","title":"Last Message At","type":"string"},"message_count":{"default":0,"title":"Message Count","type":"integer"},"page_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Page Url"},"rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rating"},"resolved":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Resolved"},"sentiment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sentiment"},"started_at":{"format":"date-time","title":"Started At","type":"string"},"status":{"title":"Status","type":"string"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"total_cost_usd":{"default":0,"title":"Total Cost Usd","type":"number"},"visitor_id":{"title":"Visitor Id","type":"string"}},"required":["id","visitor_id","status","started_at","last_message_at"],"title":"ConversationRead","type":"object"},"CustomEndpointConfig":{"properties":{"auth_header_name":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"title":"Auth Header Name"},"auth_header_value":{"anyOf":[{"maxLength":2000,"type":"string"},{"type":"null"}],"title":"Auth Header Value"},"endpoint_url":{"maxLength":1000,"minLength":8,"title":"Endpoint Url","type":"string"},"model":{"anyOf":[{"maxLength":128,"type":"string"},{"type":"null"}],"title":"Model"},"response_path":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"title":"Response Path"}},"required":["endpoint_url"],"title":"CustomEndpointConfig","type":"object"},"DarkPalette":{"additionalProperties":true,"description":"The second palette, used when the *visitor's* system is set to dark.\n\nNot the tenant's preference - the visitor's. A tenant previewing on a light\nlaptop is not the person the choice is for, and a widget that stays bright\nwhite on a dark site reads as broken rather than as branded.\n\nEvery field is optional. A tenant who sets none gets a palette derived from\ntheir light one at render time, which is a better default than forcing them\nthrough a second colour picker they did not ask for.","properties":{"border_color":{"anyOf":[{"pattern":"^#[0-9A-Fa-f]{6}$","type":"string"},{"type":"null"}],"title":"Border Color"},"bot_bubble_bg":{"anyOf":[{"pattern":"^#[0-9A-Fa-f]{6}$","type":"string"},{"type":"null"}],"title":"Bot Bubble Bg"},"bot_bubble_text":{"anyOf":[{"pattern":"^#[0-9A-Fa-f]{6}$","type":"string"},{"type":"null"}],"title":"Bot Bubble Text"},"messages_bg":{"anyOf":[{"pattern":"^#[0-9A-Fa-f]{6}$","type":"string"},{"type":"null"}],"title":"Messages Bg"},"panel_bg":{"anyOf":[{"pattern":"^#[0-9A-Fa-f]{6}$","type":"string"},{"type":"null"}],"title":"Panel Bg"},"primary_color":{"anyOf":[{"pattern":"^#[0-9A-Fa-f]{6}$","type":"string"},{"type":"null"}],"title":"Primary Color"},"user_bubble_text":{"anyOf":[{"pattern":"^#[0-9A-Fa-f]{6}$","type":"string"},{"type":"null"}],"title":"User Bubble Text"}},"title":"DarkPalette","type":"object"},"DirectoryConfig":{"description":"Generic routing table: category + choice resolves to a link.\n\nReplaces the previous hard-coded `doctors_config`. A clinic reads it as\nbranch/doctor/appointment link, a dealership as city/showroom/booking link,\na university as campus/department/enquiry form - same code, no per-vertical\nbranches.","properties":{"category_field":{"default":"branch","maxLength":40,"title":"Category Field","type":"string"},"category_label":{"default":"Location","maxLength":60,"title":"Category Label","type":"string"},"choice_field":{"default":"preferred_specialist","maxLength":40,"title":"Choice Field","type":"string"},"choice_label":{"default":"Specialist","maxLength":60,"title":"Choice Label","type":"string"},"enabled":{"default":false,"title":"Enabled","type":"boolean"},"entries":{"items":{"$ref":"#/components/schemas/DirectoryEntry"},"maxItems":500,"title":"Entries","type":"array"},"result_field":{"default":"booking_link","maxLength":40,"title":"Result Field","type":"string"}},"title":"DirectoryConfig","type":"object"},"DirectoryEntry":{"properties":{"category":{"default":"","maxLength":100,"title":"Category","type":"string"},"link":{"default":"","maxLength":1000,"title":"Link","type":"string"},"metadata":{"additionalProperties":true,"title":"Metadata","type":"object"},"name":{"maxLength":150,"minLength":1,"title":"Name","type":"string"}},"required":["name"],"title":"DirectoryEntry","type":"object"},"DocumentCreate":{"properties":{"max_pages":{"default":25,"maximum":200,"minimum":1,"title":"Max Pages","type":"integer"},"raw_text":{"anyOf":[{"maxLength":2000000,"type":"string"},{"type":"null"}],"title":"Raw Text"},"source_type":{"enum":["url","raw_text","sitemap"],"title":"Source Type","type":"string"},"tags":{"items":{"type":"string"},"maxItems":20,"title":"Tags","type":"array"},"title":{"default":"","maxLength":500,"title":"Title","type":"string"},"url":{"anyOf":[{"maxLength":2000,"type":"string"},{"type":"null"}],"title":"Url"}},"required":["source_type"],"title":"DocumentCreate","type":"object"},"DocumentDownload":{"description":"A signed link to a stored original.\n\n`expires_in` is returned so a client can decide whether to reuse the URL or\nask for a fresh one. Presigned links are bearer credentials - anybody who\nhas the string has the file until it lapses - so they are deliberately\nshort-lived and re-issued per click rather than cached in a page.","properties":{"expires_in":{"title":"Expires In","type":"integer"},"filename":{"title":"Filename","type":"string"},"mime_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mime Type"},"url":{"title":"Url","type":"string"}},"required":["url","expires_in","filename"],"title":"DocumentDownload","type":"object"},"DocumentRead":{"properties":{"chunk_count":{"default":0,"title":"Chunk Count","type":"integer"},"created_at":{"format":"date-time","title":"Created At","type":"string"},"embedding_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Embedding Model"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"id":{"title":"Id","type":"string"},"mime_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mime Type"},"size_bytes":{"default":0,"title":"Size Bytes","type":"integer"},"source_type":{"title":"Source Type","type":"string"},"source_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Url"},"status":{"title":"Status","type":"string"},"tags":{"items":{},"title":"Tags","type":"array"},"title":{"title":"Title","type":"string"},"token_count":{"default":0,"title":"Token Count","type":"integer"},"updated_at":{"format":"date-time","title":"Updated At","type":"string"}},"required":["id","source_type","title","status","created_at","updated_at"],"title":"DocumentRead","type":"object"},"DocumentStatusRead":{"description":"Polled after upload until the document reaches a terminal state.","properties":{"chunk_count":{"title":"Chunk Count","type":"integer"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"id":{"title":"Id","type":"string"},"status":{"title":"Status","type":"string"}},"required":["id","status","chunk_count"],"title":"DocumentStatusRead","type":"object"},"EmailOnlyRequest":{"description":"Shared by forgot-password, resend-verification and otp/request.\n\nAll three answer identically whether or not the address exists, so they take\nidentical input and return identical output. Giving them one schema makes\nthat symmetry visible rather than something three handlers happen to agree\non.","properties":{"email":{"format":"email","title":"Email","type":"string"}},"required":["email"],"title":"EmailOnlyRequest","type":"object"},"EncryptionState":{"properties":{"consequences":{"items":{"type":"string"},"title":"Consequences","type":"array"},"key_created_at":{"anyOf":[{},{"type":"null"}],"title":"Key Created At"},"mode":{"title":"Mode","type":"string"},"sealing":{"title":"Sealing","type":"boolean"}},"required":["mode","consequences","sealing"],"title":"EncryptionState","type":"object"},"EncryptionUpdate":{"properties":{"mode":{"enum":["platform","tenant"],"title":"Mode","type":"string"}},"required":["mode"],"title":"EncryptionUpdate","type":"object"},"EventDescriptor":{"description":"One entry in the catalogue.\n\nThe catalogue exists because a subscription list is otherwise a guessing\ngame: a customer picking events from an enum in our source is a customer\nreading our source.","properties":{"delivery":{"enum":["immediate","batched"],"title":"Delivery","type":"string"},"description":{"title":"Description","type":"string"},"example":{"additionalProperties":true,"title":"Example","type":"object"},"name":{"title":"Name","type":"string"}},"required":["name","description","delivery","example"],"title":"EventDescriptor","type":"object"},"EventsUpdate":{"properties":{"events":{"items":{"type":"string"},"maxItems":10,"minItems":1,"title":"Events","type":"array"}},"required":["events"],"title":"EventsUpdate","type":"object"},"FlowSave":{"properties":{"bot_id":{"format":"uuid","title":"Bot Id","type":"string"},"description":{"anyOf":[{"maxLength":2000,"type":"string"},{"type":"null"}],"title":"Description"},"graph":{"additionalProperties":true,"title":"Graph","type":"object"},"name":{"maxLength":120,"minLength":1,"title":"Name","type":"string"},"trigger":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trigger"}},"required":["bot_id","name","graph"],"title":"FlowSave","type":"object"},"GoogleCallbackRequest":{"properties":{"code":{"maxLength":2048,"minLength":8,"title":"Code","type":"string"},"code_verifier":{"maxLength":128,"minLength":43,"title":"Code Verifier","type":"string"},"nonce":{"anyOf":[{"maxLength":256,"type":"string"},{"type":"null"}],"title":"Nonce"}},"required":["code","code_verifier"],"title":"GoogleCallbackRequest","type":"object"},"GoogleStartResponse":{"description":"What the browser needs to begin the flow.\n\n`state`, `nonce` and `code_verifier` are generated server-side for the\nentropy, then handed back for the SPA to keep in `sessionStorage` and return\nwith the code. Holding them here instead would mean issuing a session to\nsomebody who does not have one yet - a cookie and a cleanup job, to save one\nround trip.","properties":{"authorization_url":{"title":"Authorization Url","type":"string"},"code_verifier":{"title":"Code Verifier","type":"string"},"nonce":{"title":"Nonce","type":"string"},"redirect_uri":{"title":"Redirect Uri","type":"string"},"state":{"title":"State","type":"string"}},"required":["authorization_url","state","nonce","code_verifier","redirect_uri"],"title":"GoogleStartResponse","type":"object"},"Gradient":{"description":"A two-stop linear gradient for the launcher and header.","properties":{"angle":{"default":135,"maximum":360,"minimum":0,"title":"Angle","type":"integer"},"from_color":{"pattern":"^#[0-9A-Fa-f]{6}$","title":"From Color","type":"string"},"to_color":{"pattern":"^#[0-9A-Fa-f]{6}$","title":"To Color","type":"string"}},"required":["from_color","to_color"],"title":"Gradient","type":"object"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"title":"Detail","type":"array"}},"title":"HTTPValidationError","type":"object"},"HierarchyNode":{"description":"One workspace in the tree. Recursive - a client may run clients of its\nown, up to the depth the database enforces.","properties":{"children":{"default":[],"items":{"$ref":"#/components/schemas/HierarchyNode"},"title":"Children","type":"array"},"depth":{"title":"Depth","type":"integer"},"id":{"title":"Id","type":"string"},"is_active":{"title":"Is Active","type":"boolean"},"name":{"title":"Name","type":"string"},"plan_tier":{"title":"Plan Tier","type":"string"},"slug":{"title":"Slug","type":"string"}},"required":["id","name","slug","plan_tier","is_active","depth"],"title":"HierarchyNode","type":"object"},"IdentityRead":{"properties":{"created_at":{"format":"date-time","title":"Created At","type":"string"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"last_login_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Last Login At"},"provider":{"title":"Provider","type":"string"}},"required":["provider","created_at"],"title":"IdentityRead","type":"object"},"InboxItem":{"properties":{"assigned_at":{"title":"Assigned At"},"assigned_to_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assigned To Id"},"assigned_to_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assigned To Name"},"bot_id":{"title":"Bot Id","type":"string"},"contact_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Email"},"contact_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Name"},"handoff_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Handoff Reason"},"handoff_requested_at":{"title":"Handoff Requested At"},"id":{"title":"Id","type":"string"},"last_message_at":{"title":"Last Message At"},"message_count":{"default":0,"title":"Message Count","type":"integer"},"page_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Page Url"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"visitor_id":{"title":"Visitor Id","type":"string"},"visitor_present":{"default":false,"title":"Visitor Present","type":"boolean"},"visitor_seen_at":{"title":"Visitor Seen At"},"waiting_seconds":{"default":0,"title":"Waiting Seconds","type":"integer"}},"required":["id","bot_id","visitor_id"],"title":"InboxItem","type":"object"},"InvitationCreate":{"properties":{"email":{"maxLength":320,"minLength":5,"title":"Email","type":"string"},"role":{"default":"member","enum":["admin","member","viewer"],"title":"Role","type":"string"}},"required":["email"],"title":"InvitationCreate","type":"object"},"InvitationPreview":{"description":"What the acceptance page may know before anyone has signed in.\n\nDeliberately thin. Holding the token earns the workspace's name - enough to\nanswer \"join what?\" - and nothing else: no member list, no bots, no counts.","properties":{"email":{"title":"Email","type":"string"},"expires_at":{"format":"date-time","title":"Expires At","type":"string"},"has_account":{"default":false,"title":"Has Account","type":"boolean"},"invited_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Invited By"},"organization_name":{"title":"Organization Name","type":"string"},"organization_slug":{"title":"Organization Slug","type":"string"},"role":{"anyOf":[{"$ref":"#/components/schemas/OrgRole"},{"type":"string"}],"title":"Role"}},"required":["organization_name","organization_slug","email","role","expires_at"],"title":"InvitationPreview","type":"object"},"InvitationRead":{"properties":{"accepted_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Accepted At"},"created_at":{"format":"date-time","title":"Created At","type":"string"},"email":{"title":"Email","type":"string"},"expires_at":{"format":"date-time","title":"Expires At","type":"string"},"id":{"title":"Id","type":"string"},"invited_by":{"default":"","title":"Invited By","type":"string"},"role":{"title":"Role","type":"string"},"status":{"title":"Status","type":"string"}},"required":["id","email","role","status","expires_at","created_at"],"title":"InvitationRead","type":"object"},"LLMProviderType":{"description":"`platform` uses the credentials this deployment is configured with;\n`byok` (\"bring your own key\") uses the tenant's own Anthropic key;\n`custom` posts to an owner-supplied OpenAI-compatible endpoint.","enum":["platform","byok","custom"],"title":"LLMProviderType","type":"string"},"LeadCaptureConfig":{"properties":{"enabled":{"default":false,"title":"Enabled","type":"boolean"},"fields":{"items":{"$ref":"#/components/schemas/LeadCaptureField"},"maxItems":10,"title":"Fields","type":"array"},"intro":{"anyOf":[{"maxLength":300,"type":"string"},{"type":"null"}],"title":"Intro"},"title":{"anyOf":[{"maxLength":120,"type":"string"},{"type":"null"}],"title":"Title"},"trigger":{"default":"manual","enum":["before_chat","after_n_messages","manual"],"title":"Trigger","type":"string"},"trigger_value":{"anyOf":[{"maximum":50,"minimum":1,"type":"integer"},{"type":"null"}],"default":2,"title":"Trigger Value"}},"title":"LeadCaptureConfig","type":"object"},"LeadCaptureField":{"properties":{"key":{"maxLength":40,"minLength":1,"pattern":"^[a-z][a-z0-9_]*$","title":"Key","type":"string"},"label":{"maxLength":100,"minLength":1,"title":"Label","type":"string"},"placeholder":{"anyOf":[{"maxLength":120,"type":"string"},{"type":"null"}],"title":"Placeholder"},"required":{"default":false,"title":"Required","type":"boolean"},"type":{"default":"text","enum":["text","email","phone","select","number"],"title":"Type","type":"string"}},"required":["key","label"],"title":"LeadCaptureField","type":"object"},"LoginRequest":{"properties":{"email":{"format":"email","title":"Email","type":"string"},"password":{"maxLength":200,"minLength":1,"title":"Password","type":"string"}},"required":["email","password"],"title":"LoginRequest","type":"object"},"MemberRead":{"properties":{"avatar_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Url"},"email":{"title":"Email","type":"string"},"full_name":{"title":"Full Name","type":"string"},"is_default":{"title":"Is Default","type":"boolean"},"is_verified":{"title":"Is Verified","type":"boolean"},"joined_at":{"format":"date-time","title":"Joined At","type":"string"},"last_login_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Last Login At"},"membership_id":{"title":"Membership Id","type":"string"},"role":{"anyOf":[{"$ref":"#/components/schemas/OrgRole"},{"type":"string"}],"title":"Role"},"user_id":{"title":"User Id","type":"string"}},"required":["membership_id","user_id","email","full_name","is_verified","role","is_default","joined_at"],"title":"MemberRead","type":"object"},"MemberRoleUpdate":{"properties":{"role":{"$ref":"#/components/schemas/OrgRole"}},"required":["role"],"title":"MemberRoleUpdate","type":"object"},"Message":{"description":"Simple acknowledgement for endpoints with nothing else to return.","properties":{"message":{"title":"Message","type":"string"},"ok":{"default":true,"title":"Ok","type":"boolean"}},"required":["message"],"title":"Message","type":"object"},"MessageRead":{"properties":{"citations":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Citations"},"content":{"title":"Content","type":"string"},"cost_usd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Cost Usd"},"created_at":{"format":"date-time","title":"Created At","type":"string"},"error_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Code"},"id":{"title":"Id","type":"string"},"input_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Input Tokens"},"is_error":{"default":false,"title":"Is Error","type":"boolean"},"latency_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Latency Ms"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"output_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Output Tokens"},"role":{"title":"Role","type":"string"},"ttft_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ttft Ms"}},"required":["id","role","content","created_at"],"title":"MessageRead","type":"object"},"MfaActivateRequest":{"properties":{"code":{"maxLength":16,"minLength":4,"title":"Code","type":"string"}},"required":["code"],"title":"MfaActivateRequest","type":"object"},"MfaChallengeResponse":{"description":"What `/login` returns when the account has a second factor.\n\nA distinct shape from `TokenResponse` rather than a `TokenResponse` with\nempty tokens, so a client cannot accidentally treat an unfinished sign-in\nas a finished one. `mfa_required` is the discriminator; a client that has\nnever heard of MFA sees no `access_token` and fails loudly rather than\nproceeding half-authenticated.","properties":{"challenge_token":{"title":"Challenge Token","type":"string"},"expires_in":{"title":"Expires In","type":"integer"},"mfa_required":{"default":true,"title":"Mfa Required","type":"boolean"},"recovery_available":{"default":true,"title":"Recovery Available","type":"boolean"}},"required":["challenge_token","expires_in"],"title":"MfaChallengeResponse","type":"object"},"MfaCodesResponse":{"description":"Recovery codes. Shown once; only digests are stored.","properties":{"generated_at":{"format":"date-time","title":"Generated At","type":"string"},"recovery_codes":{"items":{"type":"string"},"title":"Recovery Codes","type":"array"}},"required":["recovery_codes","generated_at"],"title":"MfaCodesResponse","type":"object"},"MfaDisableRequest":{"description":"Turning it off needs both factors, not one.\n\nThe password, because an unlocked session should not be able to remove the\ncontrol that protects the account - that is the exact scenario a second\nfactor exists for. And a current code, because otherwise a stolen session\nplus a known password strips it, which is the combination MFA is meant to\nsurvive.","properties":{"code":{"maxLength":64,"minLength":4,"title":"Code","type":"string"},"password":{"maxLength":200,"minLength":1,"title":"Password","type":"string"}},"required":["password","code"],"title":"MfaDisableRequest","type":"object"},"MfaSetupResponse":{"description":"Everything needed to enrol, returned exactly once.","properties":{"digits":{"title":"Digits","type":"integer"},"manual_key":{"title":"Manual Key","type":"string"},"period_seconds":{"title":"Period Seconds","type":"integer"},"secret":{"title":"Secret","type":"string"},"uri":{"title":"Uri","type":"string"}},"required":["secret","uri","manual_key","digits","period_seconds"],"title":"MfaSetupResponse","type":"object"},"MfaStatus":{"properties":{"activated_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Activated At"},"enabled":{"title":"Enabled","type":"boolean"},"pending":{"default":false,"title":"Pending","type":"boolean"},"recovery_codes_remaining":{"default":0,"title":"Recovery Codes Remaining","type":"integer"},"recovery_generated_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Recovery Generated At"}},"required":["enabled"],"title":"MfaStatus","type":"object"},"MfaVerifyRequest":{"properties":{"challenge_token":{"maxLength":2048,"minLength":8,"title":"Challenge Token","type":"string"},"code":{"maxLength":64,"minLength":4,"title":"Code","type":"string"}},"required":["challenge_token","code"],"title":"MfaVerifyRequest","type":"object"},"OrgRead":{"properties":{"id":{"title":"Id","type":"string"},"is_default":{"default":false,"title":"Is Default","type":"boolean"},"name":{"title":"Name","type":"string"},"parent_org_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parent Org Id"},"plan_tier":{"title":"Plan Tier","type":"string"},"role":{"anyOf":[{"$ref":"#/components/schemas/OrgRole"},{"type":"string"}],"title":"Role"},"slug":{"title":"Slug","type":"string"}},"required":["id","name","slug","plan_tier","role"],"title":"OrgRead","type":"object"},"OrgRole":{"description":"Role of a user within one organization.\n\n`owner` is the billing contact and the only role that can delete the\norganization or transfer ownership; there is always at least one.\n`viewer` is read-only, which is what a client stakeholder gets when they\nwant to watch conversation volume without being able to change a prompt.","enum":["owner","admin","member","viewer"],"title":"OrgRole","type":"string"},"OrgUpdate":{"properties":{"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"name":{"anyOf":[{"maxLength":255,"minLength":2,"type":"string"},{"type":"null"}],"title":"Name"},"settings":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Settings"}},"title":"OrgUpdate","type":"object"},"OtpVerifyRequest":{"properties":{"code":{"maxLength":6,"minLength":6,"pattern":"^\\d{6}$","title":"Code","type":"string"},"email":{"format":"email","title":"Email","type":"string"}},"required":["email","code"],"title":"OtpVerifyRequest","type":"object"},"PaginatedResponse_BotRead_":{"properties":{"has_more":{"default":false,"title":"Has More","type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/BotRead"},"title":"Items","type":"array"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"page":{"title":"Page","type":"integer"},"page_size":{"title":"Page Size","type":"integer"},"total":{"title":"Total","type":"integer"}},"required":["items","total","page","page_size"],"title":"PaginatedResponse[BotRead]","type":"object"},"PaginatedResponse_ContactRead_":{"properties":{"has_more":{"default":false,"title":"Has More","type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/ContactRead"},"title":"Items","type":"array"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"page":{"title":"Page","type":"integer"},"page_size":{"title":"Page Size","type":"integer"},"total":{"title":"Total","type":"integer"}},"required":["items","total","page","page_size"],"title":"PaginatedResponse[ContactRead]","type":"object"},"PaginatedResponse_ConversationRead_":{"properties":{"has_more":{"default":false,"title":"Has More","type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/ConversationRead"},"title":"Items","type":"array"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"page":{"title":"Page","type":"integer"},"page_size":{"title":"Page Size","type":"integer"},"total":{"title":"Total","type":"integer"}},"required":["items","total","page","page_size"],"title":"PaginatedResponse[ConversationRead]","type":"object"},"PaginatedResponse_DocumentRead_":{"properties":{"has_more":{"default":false,"title":"Has More","type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/DocumentRead"},"title":"Items","type":"array"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"page":{"title":"Page","type":"integer"},"page_size":{"title":"Page Size","type":"integer"},"total":{"title":"Total","type":"integer"}},"required":["items","total","page","page_size"],"title":"PaginatedResponse[DocumentRead]","type":"object"},"PaginatedResponse_InboxItem_":{"properties":{"has_more":{"default":false,"title":"Has More","type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/InboxItem"},"title":"Items","type":"array"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"page":{"title":"Page","type":"integer"},"page_size":{"title":"Page Size","type":"integer"},"total":{"title":"Total","type":"integer"}},"required":["items","total","page","page_size"],"title":"PaginatedResponse[InboxItem]","type":"object"},"PaginatedResponse_ToolInvocationResponse_":{"properties":{"has_more":{"default":false,"title":"Has More","type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/ToolInvocationResponse"},"title":"Items","type":"array"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"page":{"title":"Page","type":"integer"},"page_size":{"title":"Page Size","type":"integer"},"total":{"title":"Total","type":"integer"}},"required":["items","total","page","page_size"],"title":"PaginatedResponse[ToolInvocationResponse]","type":"object"},"PaginatedResponse_WebhookDeliveryResponse_":{"properties":{"has_more":{"default":false,"title":"Has More","type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/WebhookDeliveryResponse"},"title":"Items","type":"array"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"page":{"title":"Page","type":"integer"},"page_size":{"title":"Page Size","type":"integer"},"total":{"title":"Total","type":"integer"}},"required":["items","total","page","page_size"],"title":"PaginatedResponse[WebhookDeliveryResponse]","type":"object"},"PolicyRequest":{"properties":{"bot_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bot Id"},"channel":{"pattern":"^(whatsapp|telegram)$","title":"Channel","type":"string"},"daily_cap":{"anyOf":[{"maximum":2000,"minimum":1,"type":"integer"},{"type":"null"}],"title":"Daily Cap"},"destination":{"maxLength":255,"minLength":1,"title":"Destination","type":"string"},"digest":{"default":"none","pattern":"^(none|daily|weekly)$","title":"Digest","type":"string"},"digest_hour":{"default":9,"maximum":23,"minimum":0,"title":"Digest Hour","type":"integer"},"digest_weekday":{"default":1,"maximum":6,"minimum":0,"title":"Digest Weekday","type":"integer"},"events":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Events"},"intensity":{"default":"leads","pattern":"^(off|critical|leads|all|digest)$","title":"Intensity","type":"string"},"label":{"default":"","maxLength":120,"title":"Label","type":"string"},"min_lead_score":{"default":0,"maximum":100,"minimum":0,"title":"Min Lead Score","type":"integer"},"quiet_end":{"anyOf":[{"maximum":23,"minimum":0,"type":"integer"},{"type":"null"}],"title":"Quiet End"},"quiet_start":{"anyOf":[{"maximum":23,"minimum":0,"type":"integer"},{"type":"null"}],"title":"Quiet Start"},"timezone":{"default":"UTC","maxLength":64,"title":"Timezone","type":"string"}},"required":["channel","destination"],"title":"PolicyRequest","type":"object"},"PreferenceOut":{"properties":{"category":{"title":"Category","type":"string"},"description":{"title":"Description","type":"string"},"enabled":{"title":"Enabled","type":"boolean"},"label":{"title":"Label","type":"string"}},"required":["category","enabled","label","description"],"title":"PreferenceOut","type":"object"},"PreferenceUpdate":{"properties":{"category":{"$ref":"#/components/schemas/Category"},"enabled":{"title":"Enabled","type":"boolean"},"org_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Org Id"}},"required":["category","enabled"],"title":"PreferenceUpdate","type":"object"},"PreferencesOut":{"properties":{"email":{"title":"Email","type":"string"},"preferences":{"items":{"$ref":"#/components/schemas/PreferenceOut"},"title":"Preferences","type":"array"}},"required":["email","preferences"],"title":"PreferencesOut","type":"object"},"PreferencesUpdate":{"properties":{"changes":{"items":{"$ref":"#/components/schemas/PreferenceUpdate"},"maxItems":20,"minItems":1,"title":"Changes","type":"array"}},"required":["changes"],"title":"PreferencesUpdate","type":"object"},"ProactiveTrigger":{"description":"A rule for opening the conversation before the visitor does.\n\nEvaluated entirely in the browser. A server round trip per trigger would\nmultiply the highest-volume request in the system by every page view on\nevery customer site, to answer a question the client can already answer.\n\nValidated here anyway, because a rule that fires on every scroll event is a\nconfiguration a tenant should not be able to save - the cost of that\nmistake lands on their visitors and on our quota, and neither of them gets\na say.","properties":{"message":{"maxLength":300,"minLength":1,"title":"Message","type":"string"},"open_panel":{"default":false,"title":"Open Panel","type":"boolean"},"threshold":{"anyOf":[{"maximum":3600,"minimum":1,"type":"integer"},{"type":"null"}],"title":"Threshold"},"type":{"enum":["time_on_page","exit_intent","scroll_depth","url_pattern","return_visitor","idle"],"title":"Type","type":"string"},"url_pattern":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"title":"Url Pattern"}},"required":["type","message"],"title":"ProactiveTrigger","type":"object"},"RefreshRequest":{"properties":{"refresh_token":{"anyOf":[{"maxLength":500,"minLength":10,"type":"string"},{"type":"null"}],"title":"Refresh Token"}},"title":"RefreshRequest","type":"object"},"RegisterRequest":{"properties":{"company_name":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"title":"Company Name"},"email":{"format":"email","title":"Email","type":"string"},"full_name":{"maxLength":255,"minLength":1,"title":"Full Name","type":"string"},"password":{"maxLength":200,"minLength":8,"title":"Password","type":"string"}},"required":["email","password","full_name"],"title":"RegisterRequest","type":"object"},"RehearsalRequest":{"properties":{"blueprint":{"additionalProperties":true,"title":"Blueprint","type":"object"},"website_url":{"anyOf":[{"maxLength":2000,"type":"string"},{"type":"null"}],"title":"Website Url"}},"required":["blueprint"],"title":"RehearsalRequest","type":"object"},"ReplyRequest":{"properties":{"content":{"maxLength":8000,"minLength":1,"title":"Content","type":"string"}},"required":["content"],"title":"ReplyRequest","type":"object"},"ResetPasswordRequest":{"properties":{"new_password":{"maxLength":200,"minLength":8,"title":"New Password","type":"string"},"token":{"maxLength":512,"minLength":16,"title":"Token","type":"string"}},"required":["token","new_password"],"title":"ResetPasswordRequest","type":"object"},"ResolveRequest":{"properties":{"back_to_bot":{"default":true,"title":"Back To Bot","type":"boolean"}},"title":"ResolveRequest","type":"object"},"RotateSecretResponse":{"properties":{"rotated_at":{"format":"date-time","title":"Rotated At","type":"string"},"secret":{"title":"Secret","type":"string"}},"required":["secret","rotated_at"],"title":"RotateSecretResponse","type":"object"},"SavedViewCreate":{"description":"A named filter set.\n\n`filters` is free-form here and validated against the target resource's\nallow-list in the service - see `views_service.validate`. Declaring the\nshape in this schema instead would mean one model per resource and a new\none every time a list gains a filter; validating against the endpoint's own\nvocabulary keeps the two in step by construction.","properties":{"bot_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bot Id"},"filters":{"additionalProperties":true,"title":"Filters","type":"object"},"is_default":{"default":false,"title":"Is Default","type":"boolean"},"name":{"maxLength":120,"minLength":1,"title":"Name","type":"string"},"resource":{"enum":["conversations","contacts"],"title":"Resource","type":"string"}},"required":["resource","name"],"title":"SavedViewCreate","type":"object"},"SavedViewUpdate":{"properties":{"filters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Filters"},"is_default":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Default"},"name":{"anyOf":[{"maxLength":120,"minLength":1,"type":"string"},{"type":"null"}],"title":"Name"}},"title":"SavedViewUpdate","type":"object"},"ScanRequest":{"properties":{"website_url":{"maxLength":2000,"minLength":4,"title":"Website Url","type":"string"}},"required":["website_url"],"title":"ScanRequest","type":"object"},"SearchRequest":{"description":"Exposed so a tenant can see exactly what their bot retrieves for a\nquestion - the fastest way to diagnose a bad answer.","properties":{"document_ids":{"anyOf":[{"items":{"type":"string"},"maxItems":50,"type":"array"},{"type":"null"}],"title":"Document Ids"},"query":{"maxLength":1000,"minLength":1,"title":"Query","type":"string"},"top_k":{"default":5,"maximum":20,"minimum":1,"title":"Top K","type":"integer"}},"required":["query"],"title":"SearchRequest","type":"object"},"SearchResponse":{"properties":{"query":{"title":"Query","type":"string"},"results":{"items":{"$ref":"#/components/schemas/SearchResult"},"title":"Results","type":"array"},"took_ms":{"title":"Took Ms","type":"integer"}},"required":["query","results","took_ms"],"title":"SearchResponse","type":"object"},"SearchResult":{"properties":{"chunk_id":{"title":"Chunk Id","type":"string"},"content":{"title":"Content","type":"string"},"dense_rank":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Dense Rank"},"document_id":{"title":"Document Id","type":"string"},"document_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Document Title"},"lexical_rank":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lexical Rank"},"rerank_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rerank Score"},"score":{"title":"Score","type":"number"}},"required":["chunk_id","document_id","document_title","content","score"],"title":"SearchResult","type":"object"},"Simulation":{"properties":{"answers":{"items":{},"maxItems":50,"title":"Answers","type":"array"},"graph":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Graph"}},"title":"Simulation","type":"object"},"SubAccountCreate":{"properties":{"name":{"maxLength":255,"minLength":2,"title":"Name","type":"string"},"plan_tier":{"default":"free","pattern":"^free$","title":"Plan Tier","type":"string"}},"required":["name"],"title":"SubAccountCreate","type":"object"},"SubAccountRead":{"properties":{"bot_count":{"default":0,"title":"Bot Count","type":"integer"},"conversation_count":{"default":0,"title":"Conversation Count","type":"integer"},"created_at":{"format":"date-time","title":"Created At","type":"string"},"id":{"title":"Id","type":"string"},"is_active":{"title":"Is Active","type":"boolean"},"member_count":{"default":0,"title":"Member Count","type":"integer"},"name":{"title":"Name","type":"string"},"plan_tier":{"title":"Plan Tier","type":"string"},"slug":{"title":"Slug","type":"string"}},"required":["id","name","slug","plan_tier","is_active","created_at"],"title":"SubAccountRead","type":"object"},"TestMessageRequest":{"properties":{"message":{"maxLength":4000,"minLength":1,"title":"Message","type":"string"},"model":{"anyOf":[{"maxLength":128,"type":"string"},{"type":"null"}],"title":"Model"}},"required":["message"],"title":"TestMessageRequest","type":"object"},"TestMessageResponse":{"properties":{"citations":{"items":{"additionalProperties":true,"type":"object"},"title":"Citations","type":"array"},"content":{"title":"Content","type":"string"},"cost_usd":{"title":"Cost Usd","type":"number"},"input_tokens":{"title":"Input Tokens","type":"integer"},"latency_ms":{"title":"Latency Ms","type":"integer"},"model":{"title":"Model","type":"string"},"output_tokens":{"title":"Output Tokens","type":"integer"}},"required":["content","model","input_tokens","output_tokens","cost_usd","latency_ms"],"title":"TestMessageResponse","type":"object"},"ThemeGenerateRequest":{"description":"Ask for a palette instead of designing one.","properties":{"apply":{"default":false,"title":"Apply","type":"boolean"},"prompt":{"anyOf":[{"maxLength":2000,"type":"string"},{"type":"null"}],"title":"Prompt"},"website_url":{"anyOf":[{"maxLength":1000,"type":"string"},{"type":"null"}],"title":"Website Url"}},"title":"ThemeGenerateRequest","type":"object"},"TicketCreate":{"properties":{"body":{"maxLength":20000,"minLength":10,"title":"Body","type":"string"},"bot_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bot Id"},"category":{"default":"other","maxLength":32,"title":"Category","type":"string"},"custom_category":{"anyOf":[{"maxLength":80,"type":"string"},{"type":"null"}],"title":"Custom Category"},"priority":{"default":"normal","pattern":"^(low|normal|high)$","title":"Priority","type":"string"},"subject":{"maxLength":255,"minLength":3,"title":"Subject","type":"string"}},"required":["subject","body"],"title":"TicketCreate","type":"object"},"TicketRating":{"properties":{"comment":{"default":"","maxLength":2000,"title":"Comment","type":"string"},"score":{"maximum":5,"minimum":1,"title":"Score","type":"integer"}},"required":["score"],"title":"TicketRating","type":"object"},"TicketReply":{"properties":{"body":{"maxLength":20000,"minLength":1,"title":"Body","type":"string"}},"required":["body"],"title":"TicketReply","type":"object"},"TokenResponse":{"properties":{"access_token":{"title":"Access Token","type":"string"},"expires_in":{"title":"Expires In","type":"integer"},"organization":{"$ref":"#/components/schemas/OrgRead"},"refresh_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refresh Token"},"token_type":{"default":"bearer","title":"Token Type","type":"string"},"user":{"$ref":"#/components/schemas/UserRead"}},"required":["access_token","expires_in","user","organization"],"title":"TokenResponse","type":"object"},"ToolCreate":{"properties":{"auth_kind":{"default":"none","enum":["none","bearer","header","basic","query"],"title":"Auth Kind","type":"string"},"auth_name":{"anyOf":[{"maxLength":128,"type":"string"},{"type":"null"}],"title":"Auth Name"},"auth_secret":{"anyOf":[{"maxLength":4096,"type":"string"},{"type":"null"}],"title":"Auth Secret"},"auth_username":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"title":"Auth Username"},"body_mode":{"default":"arguments","enum":["none","arguments","template"],"title":"Body Mode","type":"string"},"body_template":{"title":"Body Template"},"bot_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Bot Id"},"description":{"maxLength":1024,"minLength":10,"title":"Description","type":"string"},"display_name":{"anyOf":[{"maxLength":128,"type":"string"},{"type":"null"}],"title":"Display Name"},"headers":{"additionalProperties":{"type":"string"},"title":"Headers","type":"object"},"idempotent":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Idempotent"},"input_schema":{"additionalProperties":true,"title":"Input Schema","type":"object"},"is_enabled":{"default":true,"title":"Is Enabled","type":"boolean"},"max_attempts":{"default":2,"maximum":5,"minimum":1,"title":"Max Attempts","type":"integer"},"max_response_bytes":{"default":262144,"maximum":4194304,"minimum":1024,"title":"Max Response Bytes","type":"integer"},"max_response_chars":{"default":8000,"maximum":100000,"minimum":200,"title":"Max Response Chars","type":"integer"},"method":{"default":"GET","enum":["GET","HEAD","POST","PUT","PATCH","DELETE"],"title":"Method","type":"string"},"name":{"maxLength":64,"minLength":1,"pattern":"^[a-zA-Z0-9_-]{1,64}$","title":"Name","type":"string"},"query_template":{"additionalProperties":{"type":"string"},"title":"Query Template","type":"object"},"response_path":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"title":"Response Path"},"timeout_ms":{"default":10000,"maximum":60000,"minimum":1000,"title":"Timeout Ms","type":"integer"},"url_template":{"maxLength":2048,"minLength":1,"title":"Url Template","type":"string"}},"required":["name","description","url_template"],"title":"ToolCreate","type":"object"},"ToolInvocationResponse":{"description":"One row of the action audit log.","properties":{"arguments":{"additionalProperties":true,"title":"Arguments","type":"object"},"attempts":{"title":"Attempts","type":"integer"},"bot_id":{"format":"uuid","title":"Bot Id","type":"string"},"call_id":{"title":"Call Id","type":"string"},"conversation_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Conversation Id"},"created_at":{"format":"date-time","title":"Created At","type":"string"},"duration_ms":{"title":"Duration Ms","type":"integer"},"error_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Code"},"id":{"format":"uuid","title":"Id","type":"string"},"ok":{"title":"Ok","type":"boolean"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result"},"status_code":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Status Code"},"step":{"title":"Step","type":"integer"},"tool_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Tool Id"},"tool_name":{"title":"Tool Name","type":"string"}},"required":["id","bot_id","conversation_id","tool_id","tool_name","call_id","step","arguments","ok","result","error_code","status_code","duration_ms","attempts","created_at"],"title":"ToolInvocationResponse","type":"object"},"ToolResponse":{"description":"What the API returns. Note what is absent: `auth_secret`.","properties":{"auth_configured":{"default":false,"title":"Auth Configured","type":"boolean"},"auth_kind":{"title":"Auth Kind","type":"string"},"auth_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Auth Name"},"auth_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Auth Username"},"body_mode":{"title":"Body Mode","type":"string"},"body_template":{"title":"Body Template"},"bot_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Bot Id"},"call_count":{"title":"Call Count","type":"integer"},"created_at":{"format":"date-time","title":"Created At","type":"string"},"description":{"title":"Description","type":"string"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"error_count":{"title":"Error Count","type":"integer"},"headers":{"additionalProperties":true,"title":"Headers","type":"object"},"id":{"format":"uuid","title":"Id","type":"string"},"idempotent":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Idempotent"},"input_schema":{"additionalProperties":true,"title":"Input Schema","type":"object"},"is_enabled":{"title":"Is Enabled","type":"boolean"},"last_called_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Last Called At"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"last_error_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Last Error At"},"max_attempts":{"title":"Max Attempts","type":"integer"},"max_response_bytes":{"title":"Max Response Bytes","type":"integer"},"max_response_chars":{"title":"Max Response Chars","type":"integer"},"method":{"title":"Method","type":"string"},"name":{"title":"Name","type":"string"},"org_id":{"format":"uuid","title":"Org Id","type":"string"},"query_template":{"additionalProperties":true,"title":"Query Template","type":"object"},"response_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Path"},"timeout_ms":{"title":"Timeout Ms","type":"integer"},"updated_at":{"format":"date-time","title":"Updated At","type":"string"},"url_template":{"title":"Url Template","type":"string"}},"required":["id","org_id","bot_id","name","description","display_name","input_schema","method","url_template","headers","query_template","body_mode","auth_kind","auth_name","auth_username","timeout_ms","max_response_bytes","max_response_chars","response_path","idempotent","max_attempts","is_enabled","call_count","error_count","last_called_at","last_error","last_error_at","created_at","updated_at"],"title":"ToolResponse","type":"object"},"ToolTestRequest":{"description":"Arguments for a dry run from the dashboard.","properties":{"arguments":{"additionalProperties":true,"title":"Arguments","type":"object"}},"title":"ToolTestRequest","type":"object"},"ToolTestResponse":{"properties":{"attempts":{"default":1,"title":"Attempts","type":"integer"},"content":{"title":"Content","type":"string"},"duration_ms":{"default":0,"title":"Duration Ms","type":"integer"},"error_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Code"},"ok":{"title":"Ok","type":"boolean"},"status_code":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Status Code"}},"required":["ok","content"],"title":"ToolTestResponse","type":"object"},"ToolUpdate":{"additionalProperties":false,"description":"Every field optional; only what is sent is changed.\n\nNot a subclass of `ToolBase`, because the cross-field rules there need the\nwhole record to be present. A partial update is merged onto the stored row\nand then re-validated as a whole - see `service.update_tool`.","properties":{"auth_kind":{"anyOf":[{"enum":["none","bearer","header","basic","query"],"type":"string"},{"type":"null"}],"title":"Auth Kind"},"auth_name":{"anyOf":[{"maxLength":128,"type":"string"},{"type":"null"}],"title":"Auth Name"},"auth_secret":{"anyOf":[{"maxLength":4096,"type":"string"},{"type":"null"}],"title":"Auth Secret"},"auth_username":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"title":"Auth Username"},"body_mode":{"anyOf":[{"enum":["none","arguments","template"],"type":"string"},{"type":"null"}],"title":"Body Mode"},"body_template":{"title":"Body Template"},"bot_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Bot Id"},"description":{"anyOf":[{"maxLength":1024,"minLength":10,"type":"string"},{"type":"null"}],"title":"Description"},"display_name":{"anyOf":[{"maxLength":128,"type":"string"},{"type":"null"}],"title":"Display Name"},"headers":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Headers"},"idempotent":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Idempotent"},"input_schema":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Input Schema"},"is_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Enabled"},"max_attempts":{"anyOf":[{"maximum":5,"minimum":1,"type":"integer"},{"type":"null"}],"title":"Max Attempts"},"max_response_bytes":{"anyOf":[{"maximum":4194304,"minimum":1024,"type":"integer"},{"type":"null"}],"title":"Max Response Bytes"},"max_response_chars":{"anyOf":[{"maximum":100000,"minimum":200,"type":"integer"},{"type":"null"}],"title":"Max Response Chars"},"method":{"anyOf":[{"enum":["GET","HEAD","POST","PUT","PATCH","DELETE"],"type":"string"},{"type":"null"}],"title":"Method"},"name":{"anyOf":[{"maxLength":64,"pattern":"^[a-zA-Z0-9_-]{1,64}$","type":"string"},{"type":"null"}],"title":"Name"},"query_template":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Query Template"},"response_path":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"title":"Response Path"},"timeout_ms":{"anyOf":[{"maximum":60000,"minimum":1000,"type":"integer"},{"type":"null"}],"title":"Timeout Ms"},"url_template":{"anyOf":[{"maxLength":2048,"type":"string"},{"type":"null"}],"title":"Url Template"}},"title":"ToolUpdate","type":"object"},"UserRead":{"properties":{"avatar_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Url"},"created_at":{"format":"date-time","title":"Created At","type":"string"},"email":{"title":"Email","type":"string"},"full_name":{"title":"Full Name","type":"string"},"id":{"title":"Id","type":"string"},"is_active":{"title":"Is Active","type":"boolean"},"is_verified":{"title":"Is Verified","type":"boolean"}},"required":["id","email","full_name","is_active","is_verified","created_at"],"title":"UserRead","type":"object"},"ValidationError":{"properties":{"ctx":{"title":"Context","type":"object"},"input":{"title":"Input"},"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"title":"Location","type":"array"},"msg":{"title":"Message","type":"string"},"type":{"title":"Error Type","type":"string"}},"required":["loc","msg","type"],"title":"ValidationError","type":"object"},"VariantRequest":{"properties":{"description":{"maxLength":4000,"minLength":10,"title":"Description","type":"string"},"website_url":{"anyOf":[{"maxLength":2000,"type":"string"},{"type":"null"}],"title":"Website Url"}},"required":["description"],"title":"VariantRequest","type":"object"},"VerificationStatus":{"properties":{"can_resend":{"default":true,"title":"Can Resend","type":"boolean"},"email":{"title":"Email","type":"string"},"is_verified":{"title":"Is Verified","type":"boolean"}},"required":["is_verified","email"],"title":"VerificationStatus","type":"object"},"VerifyEmailRequest":{"properties":{"token":{"maxLength":512,"minLength":16,"title":"Token","type":"string"}},"required":["token"],"title":"VerifyEmailRequest","type":"object"},"WebhookCreate":{"description":"Note what is absent: a secret.\n\nIt is generated here, from `secrets.token_urlsafe`, rather than accepted\nfrom the caller. A tenant-chosen signing key is a tenant-chosen *weak*\nsigning key eventually, and there is no reason to offer the choice - the\nreceiver has to store whatever it is told either way.","properties":{"bot_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Bot Id"},"description":{"anyOf":[{"maxLength":500,"type":"string"},{"type":"null"}],"title":"Description"},"events":{"items":{"type":"string"},"maxItems":8,"minItems":1,"title":"Events","type":"array"},"is_active":{"default":true,"title":"Is Active","type":"boolean"},"url":{"maxLength":2048,"minLength":8,"title":"Url","type":"string"}},"required":["url","events"],"title":"WebhookCreate","type":"object"},"WebhookCreated":{"description":"The creation response, and the only one that carries the secret.\n\nA separate model rather than an optional field on `WebhookResponse`, so\nthat returning the secret is something a route has to *choose* by naming\nthis type. An optional field is one careless `response_model` away from\nappearing on a list endpoint.","properties":{"api_version":{"title":"Api Version","type":"string"},"bot_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Bot Id"},"consecutive_failures":{"title":"Consecutive Failures","type":"integer"},"created_at":{"format":"date-time","title":"Created At","type":"string"},"delivery_count":{"title":"Delivery Count","type":"integer"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"disabled_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Disabled At"},"events":{"items":{"type":"string"},"title":"Events","type":"array"},"failure_count":{"title":"Failure Count","type":"integer"},"health":{"description":"One word for a status dot, derived rather than stored.\n\nStored health is health that goes stale the moment a delivery lands\nand nothing recomputes it.","readOnly":true,"title":"Health","type":"string"},"id":{"format":"uuid","title":"Id","type":"string"},"is_active":{"title":"Is Active","type":"boolean"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"last_failure_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Last Failure At"},"last_success_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Last Success At"},"org_id":{"format":"uuid","title":"Org Id","type":"string"},"secret":{"description":"The signing secret, shown exactly once. Store it now - it cannot be retrieved again, only rotated.","title":"Secret","type":"string"},"secret_hint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secret Hint"},"updated_at":{"format":"date-time","title":"Updated At","type":"string"},"url":{"title":"Url","type":"string"}},"required":["id","org_id","bot_id","url","events","description","is_active","api_version","consecutive_failures","delivery_count","failure_count","last_success_at","last_failure_at","last_error","disabled_at","created_at","updated_at","secret","health"],"title":"WebhookCreated","type":"object"},"WebhookDeliveryResponse":{"properties":{"attempts":{"title":"Attempts","type":"integer"},"created_at":{"format":"date-time","title":"Created At","type":"string"},"delivered_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Delivered At"},"duration_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Ms"},"event":{"title":"Event","type":"string"},"id":{"format":"uuid","title":"Id","type":"string"},"payload":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Payload"},"replay_of_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Replay Of Id"},"response_body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Body"},"response_status":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Response Status"},"status":{"title":"Status","type":"string"},"webhook_id":{"format":"uuid","title":"Webhook Id","type":"string"}},"required":["id","webhook_id","event","status","attempts","response_status","response_body","duration_ms","created_at","delivered_at"],"title":"WebhookDeliveryResponse","type":"object"},"WebhookResponse":{"description":"What the API returns. Note what is absent: `secret_encrypted`.","properties":{"api_version":{"title":"Api Version","type":"string"},"bot_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Bot Id"},"consecutive_failures":{"title":"Consecutive Failures","type":"integer"},"created_at":{"format":"date-time","title":"Created At","type":"string"},"delivery_count":{"title":"Delivery Count","type":"integer"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"disabled_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Disabled At"},"events":{"items":{"type":"string"},"title":"Events","type":"array"},"failure_count":{"title":"Failure Count","type":"integer"},"health":{"description":"One word for a status dot, derived rather than stored.\n\nStored health is health that goes stale the moment a delivery lands\nand nothing recomputes it.","readOnly":true,"title":"Health","type":"string"},"id":{"format":"uuid","title":"Id","type":"string"},"is_active":{"title":"Is Active","type":"boolean"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"last_failure_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Last Failure At"},"last_success_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Last Success At"},"org_id":{"format":"uuid","title":"Org Id","type":"string"},"secret_hint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secret Hint"},"updated_at":{"format":"date-time","title":"Updated At","type":"string"},"url":{"title":"Url","type":"string"}},"required":["id","org_id","bot_id","url","events","description","is_active","api_version","consecutive_failures","delivery_count","failure_count","last_success_at","last_failure_at","last_error","disabled_at","created_at","updated_at","health"],"title":"WebhookResponse","type":"object"},"WebhookTestRequest":{"description":"A test fire, sent to the real endpoint over the real path.\n\n`event` picks the shape; the payload is synthetic and marked as such. A\ntest that took a different code path from a live delivery would pass for\nan endpoint that fails in production, which is worse than no test button -\nthe same reasoning as the tools dry run.","properties":{"event":{"default":"conversation.started","title":"Event","type":"string"}},"title":"WebhookTestRequest","type":"object"},"WebhookTestResponse":{"properties":{"delivery_id":{"format":"uuid","title":"Delivery Id","type":"string"},"duration_ms":{"default":0,"title":"Duration Ms","type":"integer"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"ok":{"title":"Ok","type":"boolean"},"status_code":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Status Code"}},"required":["ok","delivery_id"],"title":"WebhookTestResponse","type":"object"},"WebhookUpdate":{"additionalProperties":false,"description":"Every field optional; only what is sent changes.","properties":{"description":{"anyOf":[{"maxLength":500,"type":"string"},{"type":"null"}],"title":"Description"},"events":{"anyOf":[{"items":{"type":"string"},"minItems":1,"type":"array"},{"type":"null"}],"title":"Events"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"url":{"anyOf":[{"maxLength":2048,"minLength":8,"type":"string"},{"type":"null"}],"title":"Url"}},"title":"WebhookUpdate","type":"object"},"WidgetTheme":{"additionalProperties":true,"description":"Widget appearance. Extra keys are kept so the dashboard can add controls\nwithout a migration; the widget ignores what it does not recognise.\n\n--------------------------------------------------------------------\nContrast is enforced, and enforced differently for the two callers\n--------------------------------------------------------------------\n\nA tenant editing colours by hand is **rejected**, with the measured ratio\nand a hex that would pass, because they can see the result and are entitled\nto choose which colour moves.\n\nA theme produced by the one-prompt generator is **repaired** before it\nreaches this class - see `generation_service._readable_theme`. Failing an\nentire bot generation because a model picked a hex nobody asked for, and\nwhich the customer will never see, would be an absurd way to lose a signup.\n\nTwo policies, one definition of readable, which is why the definition lives\nin `app.platform.contrast` and not here.","properties":{"accent_color":{"anyOf":[{"pattern":"^#[0-9A-Fa-f]{6}$","type":"string"},{"type":"null"}],"title":"Accent Color"},"avatar_url":{"anyOf":[{"maxLength":1000,"type":"string"},{"type":"null"}],"title":"Avatar Url"},"border_color":{"default":"#E2E8F0","pattern":"^#[0-9A-Fa-f]{6}$","title":"Border Color","type":"string"},"bot_bubble_bg":{"default":"#FFFFFF","pattern":"^#[0-9A-Fa-f]{6}$","title":"Bot Bubble Bg","type":"string"},"bot_bubble_text":{"default":"#0F172A","pattern":"^#[0-9A-Fa-f]{6}$","title":"Bot Bubble Text","type":"string"},"bubble_radius":{"default":16,"maximum":28,"minimum":0,"title":"Bubble Radius","type":"integer"},"bubble_radius_corners":{"anyOf":[{"items":{"type":"integer"},"maxItems":4,"minItems":4,"type":"array"},{"type":"null"}],"title":"Bubble Radius Corners"},"bubble_text":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"title":"Bubble Text"},"custom_css":{"anyOf":[{"maxLength":8000,"type":"string"},{"type":"null"}],"title":"Custom Css"},"dark":{"anyOf":[{"$ref":"#/components/schemas/DarkPalette"},{"type":"null"}]},"font":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"system","title":"Font"},"header_subtitle":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"title":"Header Subtitle"},"header_text":{"default":"#FFFFFF","pattern":"^#[0-9A-Fa-f]{6}$","title":"Header Text","type":"string"},"header_title":{"anyOf":[{"maxLength":60,"type":"string"},{"type":"null"}],"title":"Header Title"},"inline_target":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"title":"Inline Target"},"launcher_animation":{"default":"fade","enum":["none","fade","rise","pulse"],"title":"Launcher Animation","type":"string"},"launcher_label":{"anyOf":[{"maxLength":28,"type":"string"},{"type":"null"}],"title":"Launcher Label"},"launcher_shape":{"default":"circle","enum":["circle","rounded","square"],"title":"Launcher Shape","type":"string"},"launcher_size":{"default":"md","enum":["sm","md","lg"],"title":"Launcher Size","type":"string"},"launcher_style":{"default":"icon","enum":["icon","pill"],"title":"Launcher Style","type":"string"},"layout":{"default":"floating","enum":["floating","sidebar","inline","fullscreen"],"title":"Layout","type":"string"},"messages_bg":{"default":"#F8FAFC","pattern":"^#[0-9A-Fa-f]{6}$","title":"Messages Bg","type":"string"},"offset_x":{"default":20,"maximum":120,"minimum":0,"title":"Offset X","type":"integer"},"offset_y":{"default":20,"maximum":120,"minimum":0,"title":"Offset Y","type":"integer"},"panel_bg":{"default":"#FFFFFF","pattern":"^#[0-9A-Fa-f]{6}$","title":"Panel Bg","type":"string"},"panel_height":{"default":640,"maximum":900,"minimum":360,"title":"Panel Height","type":"integer"},"panel_radius":{"default":20,"maximum":32,"minimum":0,"title":"Panel Radius","type":"integer"},"panel_width":{"default":380,"maximum":520,"minimum":300,"title":"Panel Width","type":"integer"},"position":{"default":"bottom-right","enum":["bottom-right","bottom-left"],"title":"Position","type":"string"},"primary_color":{"default":"#4F46E5","pattern":"^#[0-9A-Fa-f]{6}$","title":"Primary Color","type":"string"},"primary_gradient":{"anyOf":[{"$ref":"#/components/schemas/Gradient"},{"type":"null"}]},"proactive":{"items":{"$ref":"#/components/schemas/ProactiveTrigger"},"maxItems":5,"title":"Proactive","type":"array"},"proactive_cooldown_days":{"default":7,"maximum":90,"minimum":0,"title":"Proactive Cooldown Days","type":"integer"},"show_branding":{"default":true,"title":"Show Branding","type":"boolean"},"show_citations":{"default":true,"title":"Show Citations","type":"boolean"},"theme_mode":{"default":"auto","enum":["auto","light","dark"],"title":"Theme Mode","type":"string"},"theme_version":{"default":2,"maximum":99,"minimum":1,"title":"Theme Version","type":"integer"},"typing_indicator":{"default":"dots","enum":["dots","pulse","wave","none"],"title":"Typing Indicator","type":"string"},"user_bubble_text":{"default":"#FFFFFF","pattern":"^#[0-9A-Fa-f]{6}$","title":"User Bubble Text","type":"string"}},"title":"WidgetTheme","type":"object"}},"securitySchemes":{"HTTPBearer":{"scheme":"bearer","type":"http"}}},"info":{"description":"The Integrable Cloud API.\n\nAuthenticate with `Authorization: Bearer sk_live_...`. Keys are created in the dashboard under Settings -> API keys and carry scopes; a call outside a key's scopes is refused with 403.\n\nEvery mutating request accepts `Idempotency-Key`. Every response carries `X-API-Version` and, where a budget applies, `RateLimit-*`.\n\nThere is also an MCP server at `/mcp` for connecting this workspace to Claude, ChatGPT or an editor. It uses the same API keys.","title":"integrable.cloud","version":"2026-09-03"},"openapi":"3.1.0","paths":{"/api/activity":{"get":{"description":"What has been happening in this workspace, by event.\n\nReads `event_rollup_daily`, which a handler has been maintaining since the\nevent ledger shipped and which no query had ever touched. One indexed\nupsert per dispatched event had been paying for a table nobody read.\n\nLabelled in plain language rather than by event name. An activity feed that\nsays `conversation.answer_refused` is a log file with a web page in front\nof it; one that says \"Could not answer a question\" is the panel a business\nowner scans on a Monday.","operationId":"activity_api_activity_get","parameters":[{"in":"query","name":"days","required":false,"schema":{"default":30,"maximum":365,"minimum":1,"title":"Days","type":"integer"}},{"in":"query","name":"bot_id","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bot Id"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Activity Api Activity Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Activity","tags":["insights"]}},"/api/advice/{recommendation_id}":{"patch":{"description":"Marks a recommendation acknowledged, done or dismissed.\n\nWorth having beyond tidiness: a set of recommendations nobody ever marks\ndone is measurable evidence that the advice is not landing, and that is a\nthing to fix rather than a thing to guess about.","operationId":"acknowledge_advice_api_advice__recommendation_id__patch","parameters":[{"in":"path","name":"recommendation_id","required":true,"schema":{"title":"Recommendation Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Payload","type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Acknowledge Advice","tags":["insights"]}},"/api/alerts":{"get":{"description":"What is connected, what could be, and what each option costs.\n\n`available` is filtered by what this deployment holds credentials for. A\ncustomer should never be shown a connect form for a channel that will\naccept their number and then never deliver anything.","operationId":"list_channels_api_alerts_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response List Channels Api Alerts Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Channels","tags":["alerts"]},"put":{"description":"Creates or updates a channel's settings.\n\nThe destination is normalised by the adapter before it is stored, so a\nnumber typed as `+91 98765 43210` and one typed as `09876543210` are one\nchannel rather than two - which matters because two channels to one phone\nis two messages and two bills.","operationId":"save_channel_api_alerts_put","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Save Channel Api Alerts Put","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Save Channel","tags":["alerts"]}},"/api/alerts/estimate":{"post":{"description":"What a setting would cost, before it is saved. See the module docstring.","operationId":"estimate_api_alerts_estimate_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Estimate Api Alerts Estimate Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Estimate","tags":["alerts"]}},"/api/alerts/telegram/connect":{"post":{"description":"Starts the Telegram flow by handing back a code and a link.\n\nTelegram's constraint drives the shape: the customer must message the bot\nfirst, so the product cannot ask for an id it has no way to obtain. The\ncode they send is what lets `poll` identify which chat is theirs.","operationId":"telegram_connect_api_alerts_telegram_connect_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Telegram Connect Api Alerts Telegram Connect Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Telegram Connect","tags":["alerts"]}},"/api/alerts/telegram/poll":{"post":{"description":"Looks for the code in the bot's recent messages.\n\nReturns `{\"found\": false}` rather than an error while waiting - the normal\ncase is that the customer has not sent it yet, and the dashboard polls\nthis while showing them the instructions.","operationId":"telegram_poll_api_alerts_telegram_poll_post","parameters":[{"in":"query","name":"label","required":false,"schema":{"default":"","maxLength":120,"title":"Label","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Telegram Poll Api Alerts Telegram Poll Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Telegram Poll","tags":["alerts"]}},"/api/alerts/{policy_id}":{"delete":{"operationId":"delete_channel_api_alerts__policy_id__delete","parameters":[{"in":"path","name":"policy_id","required":true,"schema":{"title":"Policy Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Delete Channel","tags":["alerts"]}},"/api/alerts/{policy_id}/test":{"post":{"description":"Sends a sample notification, exactly as a real one would look.\n\nMetered like any other message. A test that is free is a test somebody\nruns forty times, and on WhatsApp that is forty real messages we pay for.","operationId":"test_channel_api_alerts__policy_id__test_post","parameters":[{"in":"path","name":"policy_id","required":true,"schema":{"title":"Policy Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Test Channel","tags":["alerts"]}},"/api/alerts/{policy_id}/verify":{"post":{"description":"Confirms the code and marks the channel live.\n\nThe stored code is deleted whether or not it matched. A six-digit code\nthat survives a wrong guess is a code somebody can brute-force at leisure,\nand re-sending is one tap.","operationId":"finish_verification_api_alerts__policy_id__verify_post","parameters":[{"in":"path","name":"policy_id","required":true,"schema":{"title":"Policy Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Payload","type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Finish Verification","tags":["alerts"]}},"/api/alerts/{policy_id}/verify/start":{"post":{"description":"Sends a code to the destination itself.\n\nTo the destination, not to the account's email. The thing being proved is\nthat this number or chat reaches this customer - proving they can read\ntheir own inbox proves nothing about the phone number they typed.\n\nRate-limited per organisation because each WhatsApp attempt costs a real\nmessage.","operationId":"start_verification_api_alerts__policy_id__verify_start_post","parameters":[{"in":"path","name":"policy_id","required":true,"schema":{"title":"Policy Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Start Verification","tags":["alerts"]}},"/api/api-keys":{"get":{"operationId":"list_api_keys_api_api_keys_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response List Api Keys Api Api Keys Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Api Keys","tags":["dashboard"]},"post":{"description":"Creates a key. The plaintext is returned exactly once and never again -\nonly a peppered hash is stored.","operationId":"create_api_key_api_api_keys_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Payload","type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Create Api Key Api Api Keys Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Create Api Key","tags":["dashboard"]}},"/api/api-keys/{api_key_id}":{"delete":{"operationId":"revoke_api_key_api_api_keys__api_key_id__delete","parameters":[{"in":"path","name":"api_key_id","required":true,"schema":{"title":"Api Key Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Revoke Api Key","tags":["dashboard"]}},"/api/archive/import":{"post":{"description":"Reads a bundle back and returns it as a viewable report.\n\n**Writes nothing.** It parses, verifies the checksum and signature, and\nreturns a rendered view. That is what makes accepting a file from a user\nsafe at all: the worst a tampered bundle can do is render its own contents\nback to whoever uploaded it, which is what a file viewer does by\ndefinition.\n\nVerification failures are reported specifically - \"not from this product\",\n\"edited since export\", \"from a different installation\" are genuinely\ndifferent problems with different answers, and collapsing them into\n\"invalid file\" wastes the customer's time.","operationId":"import_archive_api_archive_import_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_import_archive_api_archive_import_post"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Import Archive Api Archive Import Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Import Archive","tags":["insights"]}},"/api/archive/view":{"post":{"description":"The same as `/archive/import`, for a client that already has the JSON.\n\nExists because a browser that just read the file with `FileReader` should\nnot have to re-encode it as multipart to look at it.","operationId":"view_archive_api_archive_view_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Payload","type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"View Archive","tags":["insights"]}},"/api/archives":{"get":{"description":"Which archives have been exported, by whom, and when they expire.","operationId":"list_archives_api_archives_get","parameters":[{"in":"query","name":"limit","required":false,"schema":{"default":25,"maximum":100,"minimum":1,"title":"Limit","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response List Archives Api Archives Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Archives","tags":["insights"]}},"/api/audit-log":{"get":{"description":"Who did what in this workspace.\n\n`audit_logs` has been written by identity, tenancy and the admin surface\nsince the beginning, indexed on `(org_id, created_at)`, and read by no\nendpoint in the product. This is that read.\n\nAdmin-level, not member-level: the log names people and includes IP\naddresses, and every operator impersonation of this workspace appears in\nit - which is the whole point, and also why it is not a viewer surface.","operationId":"audit_log_api_audit_log_get","parameters":[{"in":"query","name":"days","required":false,"schema":{"default":30,"maximum":365,"minimum":1,"title":"Days","type":"integer"}},{"in":"query","name":"action","required":false,"schema":{"anyOf":[{"maxLength":60,"type":"string"},{"type":"null"}],"title":"Action"}},{"in":"query","name":"limit","required":false,"schema":{"default":50,"maximum":200,"minimum":1,"title":"Limit","type":"integer"}},{"in":"query","name":"offset","required":false,"schema":{"default":0,"minimum":0,"title":"Offset","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Audit Log Api Audit Log Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Audit Log","tags":["insights"]}},"/api/auth/accept-invitation":{"post":{"description":"Joins a workspace and signs in, in one step.\n\nComposes two domains, which is exactly what a router is for: `tenancy`\ndecides what the invitation means and creates or links the account,\n`identity` issues the session. Neither service imports the other.","operationId":"accept_invitation_api_auth_accept_invitation_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptInvitationRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Accept Invitation","tags":["auth"]}},"/api/auth/change-password":{"post":{"operationId":"change_password_api_auth_change_password_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Change Password","tags":["auth"]}},"/api/auth/forgot-password":{"post":{"description":"Starts a password reset.\n\nAnswers identically for a known and an unknown address - see the section\nheader. `issue_for_email` also performs the same database work either way,\nso the timing does not leak what the wording does not.","operationId":"forgot_password_api_auth_forgot_password_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailOnlyRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Forgot Password","tags":["auth"]}},"/api/auth/google":{"post":{"description":"Exchanges a Google authorization code for a session on this platform.\n\nThe response is the same envelope as `/login`, deliberately: a client should\nnot need a second code path because the user chose a different way in.","operationId":"google_callback_api_auth_google_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleCallbackRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Google Callback","tags":["auth"]}},"/api/auth/google/start":{"get":{"description":"Everything the browser needs to begin a Google sign-in.\n\nUnauthenticated by definition. Rate-limited per IP anyway: the endpoint is\ncheap, but an open generator of authorize URLs carrying our client id is a\nsmall gift to somebody building a phishing page.","operationId":"google_start_api_auth_google_start_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleStartResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Google Start","tags":["auth"]}},"/api/auth/identities":{"get":{"description":"Which sign-in methods this account has.\n\nShown on the security page, and what the dashboard needs in order to grey\nout \"disconnect\" on the only one left.","operationId":"list_identities_api_auth_identities_get","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/IdentityRead"},"title":"Response List Identities Api Auth Identities Get","type":"array"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Identities","tags":["auth"]}},"/api/auth/identities/{provider}":{"delete":{"description":"Disconnects a provider, unless it is the only way into the account.","operationId":"unlink_identity_api_auth_identities__provider__delete","parameters":[{"in":"path","name":"provider","required":true,"schema":{"title":"Provider","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Unlink Identity","tags":["auth"]}},"/api/auth/invitation":{"get":{"description":"What the acceptance page may show before anybody has signed in.\n\nA GET with the token in the query string, because the recipient arrives by\nclicking a link. That does put the token in browser history and in any\nreferrer the page leaks - which is why it is single-use, expires in seven\ndays, and why the page should exchange it for a session promptly.","operationId":"preview_invitation_api_auth_invitation_get","parameters":[{"in":"query","name":"token","required":true,"schema":{"title":"Token","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationPreview"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Preview Invitation","tags":["auth"]}},"/api/auth/login":{"post":{"description":"Verifies a password, and issues tokens only if that is the whole story.\n\nAn account with a second factor gets an `MfaChallengeResponse` here and\nfinishes at `POST /auth/mfa/verify`. Read `mfa_required` to tell them\napart - the two shapes have no field in common by design.","operationId":"login_api_auth_login_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/TokenResponse"},{"$ref":"#/components/schemas/MfaChallengeResponse"}],"title":"Response Login Api Auth Login Post"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Login","tags":["auth"]}},"/api/auth/logout":{"post":{"operationId":"logout_api_auth_logout_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Logout","tags":["auth"]}},"/api/auth/logout-all":{"post":{"operationId":"logout_all_api_auth_logout_all_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Logout All","tags":["auth"]}},"/api/auth/me":{"get":{"operationId":"me_api_auth_me_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRead"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Me","tags":["auth"]}},"/api/auth/mfa":{"get":{"operationId":"mfa_status_api_auth_mfa_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaStatus"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Mfa Status","tags":["auth"]}},"/api/auth/mfa/activate":{"post":{"description":"Proves the authenticator works, then switches the factor on.\n\nReturns the recovery codes, once. They are generated here rather than at\nsetup because codes for a factor that was never activated are a set of\nlive secrets guarding nothing.","operationId":"activate_mfa_api_auth_mfa_activate_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaActivateRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaCodesResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Activate Mfa","tags":["auth"]}},"/api/auth/mfa/disable":{"post":{"description":"Turns the second factor off. Needs the password *and* a current code.\n\nBoth, because either one alone defeats the point. A session that could\nremove MFA with a password is a session in which a stolen password is still\nsufficient; one that could remove it with a code alone is one where the\nborrowed unlocked laptop is.\n\nA recovery code is accepted in place of an authenticator code - somebody\nwhose phone is at the bottom of a canal has to be able to turn this off,\nand they have already proved the password.","operationId":"disable_mfa_api_auth_mfa_disable_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaDisableRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Disable Mfa","tags":["auth"]}},"/api/auth/mfa/recovery-codes":{"post":{"description":"Issues a fresh set and invalidates every previous one.\n\nA current code is required. Without it, anyone holding a session could mint\nthemselves a set of long-lived credentials that survive the owner changing\ntheir password - which is a persistence mechanism, not a recovery feature.","operationId":"regenerate_recovery_codes_api_auth_mfa_recovery_codes_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaActivateRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaCodesResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Regenerate Recovery Codes","tags":["auth"]}},"/api/auth/mfa/setup":{"post":{"description":"Generates a secret. Does **not** switch the factor on.\n\nEnrolment is two steps on purpose: a one-step version locks out every user\nwhose authenticator failed to scan or whose phone clock is wrong, and their\nonly recovery is a support ticket. `POST /mfa/activate` with a working code\nis what turns it on.","operationId":"setup_mfa_api_auth_mfa_setup_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaSetupResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Setup Mfa","tags":["auth"]}},"/api/auth/mfa/verify":{"post":{"description":"Completes a sign-in that stopped at the second factor.\n\nRate limited per account and per address, the same two-sided limit login\nitself applies and for the same reason: per-address alone lets an attacker\nwork through a list of accounts, per-account alone lets a botnet spread\nacross addresses.\n\nA recovery code is accepted here as well as an authenticator code. The\nresponse says which was used, because somebody who has just spent one of\nten needs to know now rather than at zero.","operationId":"verify_mfa_api_auth_mfa_verify_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaVerifyRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Verify Mfa","tags":["auth"]}},"/api/auth/organizations":{"get":{"operationId":"my_organizations_api_auth_organizations_get","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/OrgRead"},"title":"Response My Organizations Api Auth Organizations Get","type":"array"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"My Organizations","tags":["auth"]}},"/api/auth/otp/request":{"post":{"description":"Emails a six-digit code.\n\nPasswordless sign-in and step-up authentication in one endpoint. The code is\nshort because people retype it from a phone; its security comes from the\nten-minute expiry and the five-attempt cap, not from its length.","operationId":"request_otp_api_auth_otp_request_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailOnlyRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Request Otp","tags":["auth"]}},"/api/auth/otp/verify":{"post":{"description":"Exchanges a correct code for a session.\n\nThis is a sign-in, so it returns the same envelope as `/login` and sets the\nsame cookie. A client should not have to know which of the two got them here.","operationId":"verify_otp_api_auth_otp_verify_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtpVerifyRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Verify Otp","tags":["auth"]}},"/api/auth/refresh":{"post":{"description":"Exchanges a refresh token for a new pair.\n\nRotates: the presented token is spent, and presenting it again revokes the\nwhole session family - see auth_service for why.","operationId":"refresh_api_auth_refresh_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Refresh","tags":["auth"]}},"/api/auth/register":{"post":{"description":"Creates a user, their workspace and an owner membership, then signs\nthem in.","operationId":"register_api_auth_register_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Register","tags":["auth"]}},"/api/auth/resend-verification":{"post":{"description":"Sends a fresh activation link.\n\nUnauthenticated, because the common case is somebody who signed up, lost the\nemail, and is now looking at a sign-in page they cannot get past. Requiring a\nsession in order to ask for the email that unlocks the session is a loop.","operationId":"resend_verification_api_auth_resend_verification_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailOnlyRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Resend Verification","tags":["auth"]}},"/api/auth/reset-password":{"post":{"description":"Completes a password reset.\n\nThree things happen besides setting the password, and each one closes a real\nhole: every other outstanding token for this user is spent, every session is\nrevoked, and a notification is sent. The last is the only way the legitimate\nowner learns that somebody else has just taken their account.","operationId":"reset_password_api_auth_reset_password_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Reset Password","tags":["auth"]}},"/api/auth/verification-status":{"get":{"operationId":"verification_status_api_auth_verification_status_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationStatus"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Verification Status","tags":["auth"]}},"/api/auth/verify-email":{"post":{"description":"Confirms an address from the link in the activation email.","operationId":"verify_email_api_auth_verify_email_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyEmailRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Verify Email","tags":["auth"]}},"/api/billing/checkout":{"post":{"description":"Starts a hosted checkout and returns where to send the browser.\n\nThe `org_id` goes into the provider's metadata, which is the whole reason\nan event arriving eight hours later can be resolved to a tenant without a\nlookup table anybody has to keep in sync. See `resolve_org`.","operationId":"checkout_api_billing_checkout_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Checkout Api Billing Checkout Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Checkout","tags":["billing"]}},"/api/billing/payments":{"get":{"description":"Every charge on this workspace, newest first.","operationId":"payment_history_api_billing_payments_get","parameters":[{"in":"query","name":"limit","required":false,"schema":{"default":24,"maximum":200,"minimum":1,"title":"Limit","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Payment History Api Billing Payments Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Payment History","tags":["billing"]}},"/api/billing/payments/{payment_id}/receipt":{"get":{"description":"One receipt as JSON, for rendering in the dashboard.","operationId":"receipt_api_billing_payments__payment_id__receipt_get","parameters":[{"in":"path","name":"payment_id","required":true,"schema":{"format":"uuid","title":"Payment Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Receipt Api Billing Payments  Payment Id  Receipt Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Receipt","tags":["billing"]}},"/api/billing/payments/{payment_id}/receipt.pdf":{"get":{"description":"The receipt as a PDF - the file somebody forwards to their accountant.\n\nRendered synchronously. It is one page of text from a row that is already\nin memory, so a job would add latency and a storage lifecycle to save\nsingle-digit milliseconds of request time.","operationId":"receipt_pdf_api_billing_payments__payment_id__receipt_pdf_get","parameters":[{"in":"path","name":"payment_id","required":true,"schema":{"format":"uuid","title":"Payment Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Receipt Pdf","tags":["billing"]}},"/api/billing/plans":{"get":{"description":"The price list, and which row the caller is on.\n\nReturned together because a pricing table that does not mark the current\nplan makes the customer work out where they are, and that is the one thing\nthe page already knows.","operationId":"plans_api_billing_plans_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Plans Api Billing Plans Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Plans","tags":["billing"]}},"/api/billing/portal":{"post":{"description":"A link into the provider's billing portal.\n\nSelf-serve cancellation and card updates live there. Having it is one of\nthe three cheap defences against a $30 dispute in docs/billing_details.md:\na customer who cannot find how to cancel disputes the charge instead, and\nat these price points a dispute costs more than two months of the plan.","operationId":"portal_api_billing_portal_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Portal Api Billing Portal Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Portal","tags":["billing"]}},"/api/billing/profile":{"get":{"description":"The billing address and tax registration, for the settings form.","operationId":"get_profile_api_billing_profile_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Get Profile Api Billing Profile Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Get Profile","tags":["billing"]},"put":{"description":"Updates the billing profile.\n\nChanging this does **not** rewrite past receipts. Every issued receipt\nrenders from the snapshot frozen onto its own payment row, so a corrected\ncompany name applies to future documents and leaves settled ones alone -\nwhich is the behaviour an auditor expects and the opposite of what a naive\njoin would produce.","operationId":"put_profile_api_billing_profile_put","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingProfileIn"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Put Profile","tags":["billing"]}},"/api/billing/subscription":{"get":{"description":"The plan, the balance and what it buys - the billing page header.\n\nNot owner-gated. Every dashboard needs the credit balance to render, and a\nmember seeing \"1,240 credits left\" is not a disclosure - it is the number\nthat stops them wondering why an answer was refused.","operationId":"subscription_api_billing_subscription_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Subscription Api Billing Subscription Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Subscription","tags":["billing"]}},"/api/bots":{"get":{"operationId":"list_bots_api_bots_get","parameters":[{"in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"title":"Page","type":"integer"}},{"in":"query","name":"page_size","required":false,"schema":{"default":20,"maximum":100,"minimum":1,"title":"Page Size","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_BotRead_"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Bots","tags":["bots"]},"post":{"operationId":"create_bot_api_bots_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotCreate"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRead"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Create Bot","tags":["bots"]}},"/api/bots/generate":{"post":{"description":"Builds a fully-configured bot from one plain-language description.\n\nThis is the product's main path, not a convenience wrapper: the customer\ndescribes their business, and everything the advanced screens expose -\npersona, greeting, starter questions, which details to collect and when,\nwhat to extract from conversation, routing, theme - is inferred. They open\nthe advanced screens only to disagree with something.\n\nWith `import_website`, the site is also crawled into the knowledge base in\nthe background, so the bot can answer real questions from its first minute\nrather than being an empty persona.","operationId":"generate_bot_api_bots_generate_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotGenerateRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotGenerateResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Generate Bot","tags":["bots"]}},"/api/bots/models":{"get":{"description":"Models this org's plan may select, with measured characteristics.","operationId":"available_models_api_bots_models_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Available Models Api Bots Models Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Available Models","tags":["bots"]}},"/api/bots/onboarding/rehearse":{"post":{"description":"Shows what a candidate assistant would say, before anything is live.\n\nAn assistant that refuses the first three questions a real visitor would\nask is one the owner should see refusing them in private. This is the\ndifference between a customer who adjusts the configuration and one who\npublishes it, watches it fail in front of a visitor, and leaves.","operationId":"rehearse_blueprint_api_bots_onboarding_rehearse_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RehearsalRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Rehearse Blueprint Api Bots Onboarding Rehearse Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Rehearse Blueprint","tags":["bots"]}},"/api/bots/onboarding/scan":{"post":{"description":"Reads a business's website, best pages first.\n\nSeparate from `/generate` so the dashboard can show what was found before\nspending a model call on it - \"we read your pricing, FAQ and services\npages\" is the moment a customer starts trusting the thing, and \"we could\nnot read your site\" is a much better first message than a confidently\nwrong assistant.","operationId":"scan_website_api_bots_onboarding_scan_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Scan Website Api Bots Onboarding Scan Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Scan Website","tags":["bots"]}},"/api/bots/onboarding/variants":{"post":{"description":"Three configurations to choose between.\n\nThey differ along one axis - how hard the assistant pushes for contact\ndetails - because that is a decision about the customer's business rather\nthan a preference they can adjust later. Tone and verbosity are settings;\n\"do you want callbacks or answers\" is not.","operationId":"generate_variants_api_bots_onboarding_variants_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VariantRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Generate Variants Api Bots Onboarding Variants Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Generate Variants","tags":["bots"]}},"/api/bots/{bot_id}":{"delete":{"description":"Soft delete: the bot goes offline immediately and is purged after the\nretention window, so an accidental deletion is recoverable.","operationId":"delete_bot_api_bots__bot_id__delete","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Delete Bot","tags":["bots"]},"get":{"operationId":"get_bot_api_bots__bot_id__get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRead"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Get Bot","tags":["bots"]},"patch":{"operationId":"update_bot_api_bots__bot_id__patch","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRead"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Update Bot","tags":["bots"]}},"/api/bots/{bot_id}/advice":{"get":{"description":"The most recent AI recommendations, plus the history behind them.\n\nRead, never generated. Producing one costs a real model call over a real\nwindow and takes seconds; a scheduled job writes them and this shows the\nlatest. The history is the persuasive part - a health score that went from\n54 to 71 after somebody acted on the advice is the best evidence this\nfeature can offer.","operationId":"advice_api_bots__bot_id__advice_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Advice Api Bots  Bot Id  Advice Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Advice","tags":["insights"]}},"/api/bots/{bot_id}/analytics":{"get":{"description":"Overview and daily series for one bot.\n\nCarries an `ETag`, because this is the panel a dashboard polls. A client\nthat revalidates gets a 304 and no body at all - which on a 90-day series\nis kilobytes per poll, and on a phone is the difference between a refresh\nthat feels instant and one that does not.","operationId":"bot_analytics_api_bots__bot_id__analytics_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"query","name":"date_from","required":false,"schema":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Date From"}},{"in":"query","name":"date_to","required":false,"schema":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Date To"}},{"in":"query","name":"days","required":false,"schema":{"default":30,"maximum":365,"minimum":1,"title":"Days","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"title":"Response Bot Analytics Api Bots  Bot Id  Analytics Get"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Bot Analytics","tags":["dashboard"]}},"/api/bots/{bot_id}/analytics/gaps":{"get":{"description":"Questions the bot could not answer.\n\nThe most directly actionable panel in the product: it is the evidence for\nwhat the knowledge base is missing.","operationId":"knowledge_gaps_api_bots__bot_id__analytics_gaps_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"query","name":"limit","required":false,"schema":{"default":30,"maximum":100,"minimum":1,"title":"Limit","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Knowledge Gaps Api Bots  Bot Id  Analytics Gaps Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Knowledge Gaps","tags":["dashboard"]}},"/api/bots/{bot_id}/analytics/insights":{"get":{"description":"The three numbers that answer \"is it working\".\n\nVolume tells a customer the assistant ran. This tells them whether it\nhelped: how often it resolved a conversation without a person, what people\nask about, and how often each of those topics goes wrong.\n\nReturned together rather than as three endpoints because they are read\ntogether and each is a small query - three round trips from a browser on a\nphone costs more than the queries do.","operationId":"bot_insights_api_bots__bot_id__analytics_insights_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"query","name":"days","required":false,"schema":{"default":30,"maximum":365,"minimum":1,"title":"Days","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"title":"Response Bot Insights Api Bots  Bot Id  Analytics Insights Get"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Bot Insights","tags":["dashboard"]}},"/api/bots/{bot_id}/archive":{"get":{"description":"Downloads recent conversations as a portable, verifiable bundle.\n\nThe file is self-describing JSON with a checksum and a signature, so it\ncan be kept, mailed to somebody, and brought back later to be looked at -\nincluding by a customer who has cancelled, which is a promise worth making\nand cheap to keep.\n\n`redact=true` strips names, emails, phone numbers and the visitor id while\nkeeping every transcript and every number derived from them. It exists\nbecause the most common reason to export chats is to send them to\nsomebody, and the second most common regret is having sent personal data\nwith them.","operationId":"export_archive_api_bots__bot_id__archive_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"query","name":"days","required":false,"schema":{"default":7,"maximum":31,"minimum":1,"title":"Days","type":"integer"}},{"in":"query","name":"redact","required":false,"schema":{"default":false,"title":"Redact","type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Export Archive","tags":["insights"]}},"/api/bots/{bot_id}/contacts":{"get":{"description":"One row per person, deduplicated across sessions and devices - unlike\n/conversations, which is one row per session.","operationId":"list_contacts_api_bots__bot_id__contacts_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"title":"Page","type":"integer"}},{"in":"query","name":"page_size","required":false,"schema":{"default":20,"maximum":100,"minimum":1,"title":"Page Size","type":"integer"}},{"in":"query","name":"q","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"title":"Q"}},{"in":"query","name":"leads_only","required":false,"schema":{"default":true,"title":"Leads Only","type":"boolean"}},{"in":"query","name":"sort","required":false,"schema":{"anyOf":[{"maxLength":64,"type":"string"},{"type":"null"}],"title":"Sort"}},{"in":"query","name":"cursor","required":false,"schema":{"anyOf":[{"maxLength":512,"type":"string"},{"type":"null"}],"title":"Cursor"}},{"in":"query","name":"count","required":false,"schema":{"default":true,"title":"Count","type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_ContactRead_"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Contacts","tags":["dashboard"]}},"/api/bots/{bot_id}/contacts/export":{"get":{"operationId":"export_contacts_api_bots__bot_id__contacts_export_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Export Contacts","tags":["dashboard"]}},"/api/bots/{bot_id}/contacts/{contact_id}/data":{"delete":{"description":"Article 17 erasure, in whichever of the two forms the tenant chooses.\n\n`redact` strips the identifiers and keeps the transcripts, so the analytics\nthey paid for survive and what remains points at nobody. `delete` removes\nthe conversations outright - easier to defend, and it takes their own\nhistory with it.\n\nA parameter rather than a policy, because the choice is the controller's:\nit is their lawful basis and their retention obligations, and deciding for\nthem would be us making their compliance decision for them.","operationId":"erase_subject_data_api_bots__bot_id__contacts__contact_id__data_delete","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"path","name":"contact_id","required":true,"schema":{"title":"Contact Id","type":"string"}},{"in":"query","name":"mode","required":false,"schema":{"default":"redact","pattern":"^(redact|delete)$","title":"Mode","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Erase Subject Data Api Bots  Bot Id  Contacts  Contact Id  Data Delete","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Erase Subject Data","tags":["dashboard"]},"get":{"description":"Everything held about one person, for a subject access request.\n\nArticle 15 asks for a copy of the personal data undergoing processing in a\ncommonly used electronic form. The tenant is the controller and this is\nwhat lets them answer without opening a support ticket with us.","operationId":"export_subject_data_api_bots__bot_id__contacts__contact_id__data_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"path","name":"contact_id","required":true,"schema":{"title":"Contact Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Export Subject Data Api Bots  Bot Id  Contacts  Contact Id  Data Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Export Subject Data","tags":["dashboard"]}},"/api/bots/{bot_id}/conversations":{"get":{"description":"One page of conversations.\n\n`cursor` is the mode to use for anything that walks the whole list -\nexports, infinite scroll, an integration syncing conversations. It is\nconstant-cost at any depth and stable while new conversations arrive;\n`page` is neither, and exists because a numbered pager needs it.\n\n`search_transcript=true` widens `q` from metadata - visitor, page, contact\ndetails, title - to what was actually *said*, using the full-text index\nthat has been in the schema since the first migration and, until now, was\nreferenced by no query in the codebase.\n\n`count=false` skips the `COUNT(*)`, which is the half of the request that\nscans. `total` comes back as -1 and `has_more` is the field to read.\n\n`outcome`, `sentiment`, `intent`, `min_rating` / `max_rating`,\n`min_lead_score` and the date bounds are what make the insight panels\nlead somewhere. Before them, the dashboard could tell a customer that 22%\nof their pricing conversations were refused and offer no way to open those\ntwelve conversations - which is a report, not a tool.","operationId":"list_conversations_api_bots__bot_id__conversations_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"title":"Page","type":"integer"}},{"in":"query","name":"page_size","required":false,"schema":{"default":20,"maximum":100,"minimum":1,"title":"Page Size","type":"integer"}},{"in":"query","name":"status","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"in":"query","name":"has_lead","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Lead"}},{"in":"query","name":"q","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"title":"Q"}},{"in":"query","name":"search_transcript","required":false,"schema":{"default":false,"title":"Search Transcript","type":"boolean"}},{"in":"query","name":"sort","required":false,"schema":{"anyOf":[{"maxLength":64,"type":"string"},{"type":"null"}],"title":"Sort"}},{"in":"query","name":"cursor","required":false,"schema":{"anyOf":[{"maxLength":512,"type":"string"},{"type":"null"}],"title":"Cursor"}},{"in":"query","name":"count","required":false,"schema":{"default":true,"title":"Count","type":"boolean"}},{"in":"query","name":"fields","required":false,"schema":{"anyOf":[{"maxLength":500,"type":"string"},{"type":"null"}],"title":"Fields"}},{"in":"query","name":"outcome","required":false,"schema":{"anyOf":[{"pattern":"^(resolved|refused|handed_off|abandoned|errored)$","type":"string"},{"type":"null"}],"title":"Outcome"}},{"in":"query","name":"sentiment","required":false,"schema":{"anyOf":[{"pattern":"^(positive|neutral|negative)$","type":"string"},{"type":"null"}],"title":"Sentiment"}},{"in":"query","name":"intent","required":false,"schema":{"anyOf":[{"maxLength":48,"type":"string"},{"type":"null"}],"title":"Intent"}},{"in":"query","name":"min_rating","required":false,"schema":{"anyOf":[{"maximum":5,"minimum":1,"type":"integer"},{"type":"null"}],"title":"Min Rating"}},{"in":"query","name":"max_rating","required":false,"schema":{"anyOf":[{"maximum":5,"minimum":1,"type":"integer"},{"type":"null"}],"title":"Max Rating"}},{"in":"query","name":"min_lead_score","required":false,"schema":{"anyOf":[{"maximum":100,"minimum":0,"type":"integer"},{"type":"null"}],"title":"Min Lead Score"}},{"in":"query","name":"unrated","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Unrated"}},{"in":"query","name":"date_from","required":false,"schema":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Date From"}},{"in":"query","name":"date_to","required":false,"schema":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Date To"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_ConversationRead_"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Conversations","tags":["dashboard"]}},"/api/bots/{bot_id}/conversations/bulk":{"post":{"description":"Resolve, reopen or delete a batch of conversations.\n\nEvery item reports its own outcome. A bulk endpoint that returns `200 OK`\nafter partially failing is worse than one that does not exist, because the\noperator believes it worked and finds out from a customer.\n\nThe batch is capped rather than queued. At 200 items this comfortably fits\ninside a request; the point at which it would not is the point at which the\nright answer is a job, not a longer timeout.","operationId":"bulk_update_conversations_api_bots__bot_id__conversations_bulk_post","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkConversationUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Bulk Update Conversations","tags":["dashboard"]}},"/api/bots/{bot_id}/conversations/{conversation_id}":{"get":{"operationId":"get_conversation_api_bots__bot_id__conversations__conversation_id__get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"path","name":"conversation_id","required":true,"schema":{"title":"Conversation Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationDetail"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Get Conversation","tags":["dashboard"]}},"/api/bots/{bot_id}/dashboard":{"get":{"description":"One bot's dashboard, at whichever depth the reader asked for.\n\nCarries an ETag. This is the panel a dashboard polls and the advanced\npayload is tens of kilobytes; a client that revalidates gets a 304 and no\nbody, which on a phone is the difference between a refresh that feels\ninstant and one that does not.","operationId":"bot_dashboard_api_bots__bot_id__dashboard_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"query","name":"days","required":false,"schema":{"default":30,"maximum":365,"minimum":1,"title":"Days","type":"integer"}},{"in":"query","name":"mode","required":false,"schema":{"anyOf":[{"pattern":"^(simple|advanced)$","type":"string"},{"type":"null"}],"title":"Mode"}},{"in":"query","name":"compare","required":false,"schema":{"default":true,"title":"Compare","type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"title":"Response Bot Dashboard Api Bots  Bot Id  Dashboard Get"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Bot Dashboard","tags":["insights"]}},"/api/bots/{bot_id}/duplicate":{"post":{"operationId":"duplicate_bot_api_bots__bot_id__duplicate_post","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRead"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Duplicate Bot","tags":["bots"]}},"/api/bots/{bot_id}/embed":{"get":{"description":"The snippet a customer pastes, in two forms.\n\n`snippet` is the one almost everybody wants: a stable URL that picks up\nevery widget improvement without them touching their HTML again.\n\n`pinned_snippet` is for the customer whose change-control process forbids a\nthird-party script that can change under them - which is most enterprises,\nand the question arrives during a security review rather than during a\ntrial. It names the content-hashed build and carries an `integrity` hash,\nso the browser refuses to execute anything but the exact bytes that were\nreviewed.\n\nPinning is offered, never defaulted. A pinned embed stops receiving fixes,\nincluding security ones, until somebody edits their page - so it has to be\na decision the customer makes rather than one we make for them.","operationId":"get_embed_api_bots__bot_id__embed_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Get Embed Api Bots  Bot Id  Embed Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Get Embed","tags":["bots"]}},"/api/bots/{bot_id}/funnel":{"get":{"description":"Impressions, opens and abandonment - the funnel above the first message.\n\nEverything else in the dashboard starts counting at a conversation, which\nmeans the most-asked question of month two has never had an answer here.","operationId":"get_funnel_api_bots__bot_id__funnel_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"query","name":"days","required":false,"schema":{"default":30,"maximum":365,"minimum":1,"title":"Days","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Get Funnel Api Bots  Bot Id  Funnel Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Get Funnel","tags":["bots"]}},"/api/bots/{bot_id}/intents":{"get":{"description":"What visitors wanted, who is worth calling back, and what to fix.\n\n`coverage` comes back with every panel built on classification. A\nbreakdown covering 12% of conversations is not wrong, but presenting it\nwithout saying so invites reading a sample as the whole - and the\nclassifier runs on a schedule, so on a busy day it is genuinely behind.","operationId":"intents_api_bots__bot_id__intents_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"query","name":"days","required":false,"schema":{"default":30,"maximum":365,"minimum":1,"title":"Days","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Intents Api Bots  Bot Id  Intents Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Intents","tags":["insights"]}},"/api/bots/{bot_id}/knowledge":{"get":{"operationId":"list_documents_api_bots__bot_id__knowledge_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"title":"Page","type":"integer"}},{"in":"query","name":"page_size","required":false,"schema":{"default":50,"maximum":100,"minimum":1,"title":"Page Size","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_DocumentRead_"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Documents","tags":["knowledge-base"]},"post":{"description":"Adds pasted text, a single URL, or a whole site to the knowledge base.\n\nURLs and sitemaps are fetched by a worker, not here: reaching an arbitrary\nthird-party site can take twenty seconds and fail in a dozen ways, none of\nwhich should happen while a customer waits on a form.","operationId":"create_document_api_bots__bot_id__knowledge_post","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentCreate"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentRead"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Create Document","tags":["knowledge-base"]}},"/api/bots/{bot_id}/knowledge/search":{"post":{"description":"Runs the bot's own retrieval and shows exactly what comes back.\n\nThe fastest way to diagnose a bad answer: it separates \"the model reasoned\npoorly\" from \"the right passage was never retrieved\", which are different\nproblems with different fixes.","operationId":"search_knowledge_api_bots__bot_id__knowledge_search_post","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Search Knowledge","tags":["knowledge-base"]}},"/api/bots/{bot_id}/knowledge/upload":{"post":{"description":"Accepts a file upload.\n\nThe size cap is enforced **while reading**, not after. `await file.read()`\non an unbounded upload buffers the whole body into memory first, so a\nsingle large request can exhaust a 512 MB container before any check runs -\nwhich is a denial-of-service an authenticated user can trigger by accident.","operationId":"upload_document_api_bots__bot_id__knowledge_upload_post","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_document_api_bots__bot_id__knowledge_upload_post"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentRead"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Upload Document","tags":["knowledge-base"]}},"/api/bots/{bot_id}/knowledge/{document_id}":{"delete":{"operationId":"delete_document_api_bots__bot_id__knowledge__document_id__delete","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"path","name":"document_id","required":true,"schema":{"title":"Document Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Delete Document","tags":["knowledge-base"]}},"/api/bots/{bot_id}/knowledge/{document_id}/download":{"get":{"description":"A short-lived signed link to the file the customer originally uploaded.\n\nReturns the URL rather than the bytes. Proxying a download through the API\nholds a worker for as long as somebody's connection lasts, which is a poor\nuse of a small container when the object store does this natively - and the\nsignature is what enforces the tenant boundary, not the redirect.\n\n404 rather than 204 when no original exists, because \"this document has no\nstored source\" and \"no such document\" are the same answer to a caller: there\nis nothing here to download. Documents added as pasted text or crawled URLs\nnever had a source file, and documents uploaded before this shipped were not\nkept.","operationId":"download_document_api_bots__bot_id__knowledge__document_id__download_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"path","name":"document_id","required":true,"schema":{"title":"Document Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentDownload"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Download Document","tags":["knowledge-base"]}},"/api/bots/{bot_id}/knowledge/{document_id}/reindex":{"post":{"operationId":"reindex_document_api_bots__bot_id__knowledge__document_id__reindex_post","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"path","name":"document_id","required":true,"schema":{"title":"Document Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Reindex Document","tags":["knowledge-base"]}},"/api/bots/{bot_id}/knowledge/{document_id}/status":{"get":{"description":"Polled after upload until the document reaches a terminal state.","operationId":"document_status_api_bots__bot_id__knowledge__document_id__status_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"path","name":"document_id","required":true,"schema":{"title":"Document Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentStatusRead"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Document Status","tags":["knowledge-base"]}},"/api/bots/{bot_id}/report":{"get":{"description":"The whole dashboard as a file, in any of five formats.\n\nAll five are renderings of one `Report` object, which is the property that\nmatters: a customer who exports the same period as a spreadsheet and as a\nPDF and finds two different numbers has learned something about this\nproduct that no amount of later accuracy undoes.\n\n`advanced` by default here, unlike the screen. Somebody who chose to\ndownload a file has asked for the data; the mode switch inside the HTML\nexport still lets them read it simply.","operationId":"bot_report_api_bots__bot_id__report_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"query","name":"format","required":false,"schema":{"default":"html","pattern":"^(html|xlsx|pdf|csv|json)$","title":"Format","type":"string"}},{"in":"query","name":"days","required":false,"schema":{"default":30,"maximum":365,"minimum":1,"title":"Days","type":"integer"}},{"in":"query","name":"mode","required":false,"schema":{"default":"advanced","pattern":"^(simple|advanced)$","title":"Mode","type":"string"}},{"in":"query","name":"include_usage","required":false,"schema":{"default":true,"title":"Include Usage","type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Bot Report","tags":["insights"]}},"/api/bots/{bot_id}/rotate-key":{"post":{"description":"Issues a new embed key. Every existing embed of this bot stops working.","operationId":"rotate_key_api_bots__bot_id__rotate_key_post","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRead"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Rotate Key","tags":["bots"]}},"/api/bots/{bot_id}/satisfaction":{"get":{"description":"CSAT and sentiment, with the trend and the conversations behind it.\n\nBoth numbers have been collected since the widget shipped and aggregated\nby nothing. This endpoint adds no writes and no dependency - the whole cost\nof the feature had already been paid.","operationId":"satisfaction_api_bots__bot_id__satisfaction_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"query","name":"days","required":false,"schema":{"default":30,"maximum":365,"minimum":1,"title":"Days","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Satisfaction Api Bots  Bot Id  Satisfaction Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Satisfaction","tags":["insights"]}},"/api/bots/{bot_id}/suggest-improvements":{"post":{"description":"Reviews the questions this bot answered badly and proposes fixes.\n\nCloses the loop that manual prompt engineering leaves open - the failures\nare already recorded, and nobody reads transcripts by hand.","operationId":"suggest_improvements_api_bots__bot_id__suggest_improvements_post","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Suggest Improvements Api Bots  Bot Id  Suggest Improvements Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Suggest Improvements","tags":["bots"]}},"/api/bots/{bot_id}/test":{"post":{"description":"Sends one message through the same retrieval and generation path the\nwidget uses, without creating a conversation.\n\nRate-limited despite being authenticated: it is an unmetered paid model\ncall, and an authenticated user scripting it is a cost-denial vector as\nreal as an anonymous one.","operationId":"test_message_api_bots__bot_id__test_post","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestMessageRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestMessageResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Test Message","tags":["bots"]}},"/api/bots/{bot_id}/theme/avatar":{"delete":{"description":"Removes the avatar and clears the theme field.\n\nThe field is cleared even when the object could not be deleted. The tenant\nasked to stop showing the image; refusing that because storage was\nunreachable would leave it on their website to protect an invariant only we\ncare about. The orphaned object is caught by the storage reconcile.","operationId":"delete_avatar_api_bots__bot_id__theme_avatar_delete","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Delete Avatar","tags":["bots"]},"post":{"description":"Uploads the assistant's avatar and points the theme at it.\n\n`widget_theme.avatar_url` has been settable since themes existed, with\nnothing behind it - a tenant could name an image they hosted themselves and\nhad no way to supply one otherwise. Object storage removed that blocker on\n2026-08-29; this is the endpoint that was left.\n\nThe size cap is enforced *while reading*, as it is on document upload and\nfor the same reason: `await file.read()` on an unbounded body buffers the\nwhole thing before any check runs, so one large request can exhaust the\ncontainer before the limit is consulted.\n\nThe file's type is read from its bytes, never from the `Content-Type` the\nuploader claims - see `app.platform.images`. The stored object is served to\nevery visitor of the tenant's website, and an attacker-chosen type there is\nhow an avatar becomes `text/html` on our own origin.","operationId":"upload_avatar_api_bots__bot_id__theme_avatar_post","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_avatar_api_bots__bot_id__theme_avatar_post"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Upload Avatar Api Bots  Bot Id  Theme Avatar Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Upload Avatar","tags":["bots"]}},"/api/bots/{bot_id}/theme/generate":{"post":{"description":"A palette from a sentence, or from the customer's own website.\n\nReturns the theme without saving it unless `apply` is set. A colour scheme\nis the most visible thing about a widget and the cheapest to disagree with,\nso the default is to propose rather than to change - the tenant sees it in\nthe preview and decides.\n\nThe palette is contrast-corrected before it is returned, not validated and\nrejected. Failing this request because a model chose a slightly too-light\ngrey would leave the customer with an error about a hex code they never\npicked; correcting it and telling them what changed is the useful version\nof the same rule. See `theme_service.readable_theme`.","operationId":"generate_theme_api_bots__bot_id__theme_generate_post","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThemeGenerateRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Generate Theme Api Bots  Bot Id  Theme Generate Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Generate Theme","tags":["bots"]}},"/api/bots/{bot_id}/traffic":{"get":{"description":"Website traffic, not just widget traffic.\n\nThe denominator the funnel never had: how many people were on the site at\nall. \"42 opens\" is a number with no scale; \"42 of 3,140 visitors\" is the\nthing that makes a free customer upgrade.","operationId":"traffic_api_bots__bot_id__traffic_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"query","name":"days","required":false,"schema":{"default":30,"maximum":365,"minimum":1,"title":"Days","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Traffic Api Bots  Bot Id  Traffic Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Traffic","tags":["insights"]}},"/api/bots/{bot_id}/versions":{"get":{"operationId":"list_versions_api_bots__bot_id__versions_get","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/BotVersionRead"},"title":"Response List Versions Api Bots  Bot Id  Versions Get","type":"array"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Versions","tags":["bots"]}},"/api/bots/{bot_id}/versions/{version}/restore":{"post":{"operationId":"restore_version_api_bots__bot_id__versions__version__restore_post","parameters":[{"in":"path","name":"bot_id","required":true,"schema":{"title":"Bot Id","type":"string"}},{"in":"path","name":"version","required":true,"schema":{"title":"Version","type":"integer"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRead"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Restore Version","tags":["bots"]}},"/api/calendars":{"get":{"operationId":"list_calendars_api_calendars_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response List Calendars Api Calendars Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Calendars","tags":["calendars"]}},"/api/calendars/bookings/upcoming":{"get":{"operationId":"list_upcoming_api_calendars_bookings_upcoming_get","parameters":[{"in":"query","name":"limit","required":false,"schema":{"default":50,"maximum":200,"minimum":1,"title":"Limit","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response List Upcoming Api Calendars Bookings Upcoming Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Upcoming","tags":["calendars"]}},"/api/calendars/bookings/{booking_id}/cancel":{"post":{"operationId":"cancel_booking_api_calendars_bookings__booking_id__cancel_post","parameters":[{"in":"path","name":"booking_id","required":true,"schema":{"title":"Booking Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Cancel Booking","tags":["calendars"]}},"/api/calendars/connect/{provider}":{"get":{"description":"Starts a connect flow. Returns the URL for the browser to visit.","operationId":"connect_api_calendars_connect__provider__get","parameters":[{"in":"path","name":"provider","required":true,"schema":{"title":"Provider","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Connect","tags":["calendars"]}},"/api/calendars/{connection_id}":{"delete":{"description":"Removes the connection. Bookings already made survive it.\n\n`calendar_bookings.connection_id` is `ON DELETE SET NULL` precisely so that\ndisconnecting a diary does not erase the record of appointments booked\nthrough it - those happened, and the customer may still need to find them.","operationId":"disconnect_api_calendars__connection_id__delete","parameters":[{"in":"path","name":"connection_id","required":true,"schema":{"title":"Connection Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Disconnect","tags":["calendars"]},"patch":{"operationId":"update_connection_api_calendars__connection_id__patch","parameters":[{"in":"path","name":"connection_id","required":true,"schema":{"title":"Connection Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionSettings"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Update Connection","tags":["calendars"]}},"/api/calendars/{connection_id}/availability":{"get":{"operationId":"get_availability_api_calendars__connection_id__availability_get","parameters":[{"in":"path","name":"connection_id","required":true,"schema":{"title":"Connection Id","type":"string"}},{"in":"query","name":"days","required":false,"schema":{"default":14,"maximum":60,"minimum":1,"title":"Days","type":"integer"}},{"in":"query","name":"limit","required":false,"schema":{"default":12,"maximum":50,"minimum":1,"title":"Limit","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Get Availability Api Calendars  Connection Id  Availability Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Get Availability","tags":["calendars"]}},"/api/calendars/{connection_id}/book":{"post":{"operationId":"create_booking_api_calendars__connection_id__book_post","parameters":[{"in":"path","name":"connection_id","required":true,"schema":{"title":"Connection Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Create Booking Api Calendars  Connection Id  Book Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Create Booking","tags":["calendars"]}},"/api/credits":{"get":{"description":"The balance, where it is going, and when it runs out.\n\nThree things together because they are read together and each is one small\nquery. The forecast is the part that changes behaviour: \"1,240 credits\nleft\" invites no action, and \"at this rate you run out on the 19th\" does.","operationId":"credits_api_credits_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Credits Api Credits Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Credits","tags":["insights"]}},"/api/credits/export":{"get":{"description":"The statement as a file - the thing somebody sends to their accountant.","operationId":"export_statement_api_credits_export_get","parameters":[{"in":"query","name":"format","required":false,"schema":{"default":"xlsx","pattern":"^(csv|xlsx|json|pdf|html)$","title":"Format","type":"string"}},{"in":"query","name":"days","required":false,"schema":{"default":90,"maximum":400,"minimum":1,"title":"Days","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Export Statement","tags":["insights"]}},"/api/credits/statement":{"get":{"description":"Every draw on the balance, newest first, with a running total.\n\nCursor-paginated. A statement is exactly the surface somebody scrolls to\nthe bottom of, and offset paging both costs more with depth and silently\nrepeats rows when a new charge lands mid-scroll - which on a billing page\nreads as being charged twice.","operationId":"statement_api_credits_statement_get","parameters":[{"in":"query","name":"days","required":false,"schema":{"default":30,"maximum":400,"minimum":1,"title":"Days","type":"integer"}},{"in":"query","name":"kind","required":false,"schema":{"anyOf":[{"maxLength":32,"type":"string"},{"type":"null"}],"title":"Kind"}},{"in":"query","name":"bot_id","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bot Id"}},{"in":"query","name":"limit","required":false,"schema":{"default":50,"maximum":200,"minimum":1,"title":"Limit","type":"integer"}},{"in":"query","name":"cursor","required":false,"schema":{"anyOf":[{"maxLength":512,"type":"string"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Statement Api Credits Statement Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Statement","tags":["insights"]}},"/api/dashboard":{"get":{"description":"Every bot in the organisation, rolled up and compared.\n\nThe gap this closes: `/overview` was the only cross-bot view, its window\nwas hard-coded, and it showed no satisfaction and no per-bot comparison. A\ncustomer with four assistants had to open four pages to find out which one\nwas working.","operationId":"org_dashboard_api_dashboard_get","parameters":[{"in":"query","name":"days","required":false,"schema":{"default":30,"maximum":365,"minimum":1,"title":"Days","type":"integer"}},{"in":"query","name":"mode","required":false,"schema":{"anyOf":[{"pattern":"^(simple|advanced)$","type":"string"},{"type":"null"}],"title":"Mode"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Org Dashboard Api Dashboard Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Org Dashboard","tags":["insights"]}},"/api/destinations":{"get":{"description":"What is connected, and what could be.\n\n`available` is filtered by what this deployment holds credentials for. A\ncustomer should never be shown a connect button that leads to somebody\nelse's consent screen and an error about a missing client id.","operationId":"list_destinations_api_destinations_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response List Destinations Api Destinations Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Destinations","tags":["destinations"]}},"/api/destinations/{connection_id}":{"delete":{"operationId":"remove_api_destinations__connection_id__delete","parameters":[{"in":"path","name":"connection_id","required":true,"schema":{"title":"Connection Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Remove","tags":["destinations"]}},"/api/destinations/{connection_id}/events":{"put":{"operationId":"update_events_api_destinations__connection_id__events_put","parameters":[{"in":"path","name":"connection_id","required":true,"schema":{"title":"Connection Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventsUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Update Events","tags":["destinations"]}},"/api/destinations/{provider}/connect":{"post":{"operationId":"start_connect_api_destinations__provider__connect_post","parameters":[{"in":"path","name":"provider","required":true,"schema":{"title":"Provider","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Start Connect","tags":["destinations"]}},"/api/exports":{"get":{"description":"What this workspace has downloaded. See `_record_export`.","operationId":"list_exports_api_exports_get","parameters":[{"in":"query","name":"limit","required":false,"schema":{"default":25,"maximum":100,"minimum":1,"title":"Limit","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response List Exports Api Exports Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Exports","tags":["insights"]}},"/api/exports/formats":{"get":{"description":"What can be downloaded and what each format is for.","operationId":"export_formats_api_exports_formats_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Export Formats Api Exports Formats Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Export Formats","tags":["insights"]}},"/api/flows":{"get":{"operationId":"list_flows_api_flows_get","parameters":[{"in":"query","name":"bot_id","required":false,"schema":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Bot Id"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response List Flows Api Flows Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Flows","tags":["flows"]},"post":{"operationId":"create_flow_api_flows_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowSave"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Create Flow Api Flows Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Create Flow","tags":["flows"]}},"/api/flows/{flow_id}":{"delete":{"operationId":"delete_flow_api_flows__flow_id__delete","parameters":[{"in":"path","name":"flow_id","required":true,"schema":{"title":"Flow Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Delete Flow","tags":["flows"]},"put":{"operationId":"update_flow_api_flows__flow_id__put","parameters":[{"in":"path","name":"flow_id","required":true,"schema":{"title":"Flow Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowSave"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Update Flow Api Flows  Flow Id  Put","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Update Flow","tags":["flows"]}},"/api/flows/{flow_id}/analytics":{"get":{"description":"Where visitors stop.\n\nThe one question a customer actually asks of a flow, and the reason the\ninterpreter records the path each run took.","operationId":"flow_analytics_api_flows__flow_id__analytics_get","parameters":[{"in":"path","name":"flow_id","required":true,"schema":{"title":"Flow Id","type":"string"}},{"in":"query","name":"days","required":false,"schema":{"default":30,"maximum":365,"minimum":1,"title":"Days","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Flow Analytics Api Flows  Flow Id  Analytics Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Flow Analytics","tags":["flows"]}},"/api/flows/{flow_id}/publish":{"post":{"description":"Makes the draft the version visitors walk through.","operationId":"publish_flow_api_flows__flow_id__publish_post","parameters":[{"in":"path","name":"flow_id","required":true,"schema":{"title":"Flow Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Publish Flow Api Flows  Flow Id  Publish Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Publish Flow","tags":["flows"]}},"/api/flows/{flow_id}/simulate":{"post":{"description":"Walks a flow with canned answers. Changes nothing.\n\nTakes an optional `graph` so an editor can preview unsaved edits - the\ncommon case, since the reason to preview is to check a change before\ncommitting to it.","operationId":"simulate_flow_api_flows__flow_id__simulate_post","parameters":[{"in":"path","name":"flow_id","required":true,"schema":{"title":"Flow Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Simulation"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Simulate Flow Api Flows  Flow Id  Simulate Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Simulate Flow","tags":["flows"]}},"/api/inbox":{"get":{"description":"Everyone waiting for a person, longest wait first.\n\nOldest first, which is the opposite of every other list in this API and is\ndeliberate: a queue served newest-first is one where the person who has\nwaited longest waits forever.\n\n`total` is -1 - this is a keyset-paginated queue with no count. The number\nan agent needs is on each row (`waiting_seconds`), not in a total.","operationId":"list_inbox_api_inbox_get","parameters":[{"in":"query","name":"mine","required":false,"schema":{"default":false,"title":"Mine","type":"boolean"}},{"in":"query","name":"unassigned","required":false,"schema":{"default":false,"title":"Unassigned","type":"boolean"}},{"in":"query","name":"bot_id","required":false,"schema":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Bot Id"}},{"in":"query","name":"limit","required":false,"schema":{"default":25,"maximum":100,"minimum":1,"title":"Limit","type":"integer"}},{"in":"query","name":"cursor","required":false,"schema":{"anyOf":[{"maxLength":512,"type":"string"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_InboxItem_"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Inbox","tags":["inbox"]}},"/api/inbox/{conversation_id}/claim":{"post":{"description":"Takes ownership of a waiting conversation.\n\nConflicts - 409 - if another agent claimed it first. That is the expected\noutcome of two people working the same inbox, not an error condition, and\nthe message names the situation so the client can refresh rather than\nretry.","operationId":"claim_api_inbox__conversation_id__claim_post","parameters":[{"in":"path","name":"conversation_id","required":true,"schema":{"format":"uuid","title":"Conversation Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Claim Api Inbox  Conversation Id  Claim Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Claim","tags":["inbox"]}},"/api/inbox/{conversation_id}/release":{"post":{"description":"Puts it back in the unassigned queue for somebody else.","operationId":"release_api_inbox__conversation_id__release_post","parameters":[{"in":"path","name":"conversation_id","required":true,"schema":{"format":"uuid","title":"Conversation Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Release","tags":["inbox"]}},"/api/inbox/{conversation_id}/reply":{"post":{"description":"Sends a message the visitor will see.\n\nWritten as an assistant-role message carrying `author_user_id` - see\n`handoff_service` for why that is not a new role. The visitor's widget\npicks it up on its next poll of `/messages`.","operationId":"reply_api_inbox__conversation_id__reply_post","parameters":[{"in":"path","name":"conversation_id","required":true,"schema":{"format":"uuid","title":"Conversation Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplyRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Reply Api Inbox  Conversation Id  Reply Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Reply","tags":["inbox"]}},"/api/inbox/{conversation_id}/resolve":{"post":{"description":"Ends the human's involvement.\n\nBy default the assistant resumes, because most handoffs are one question in\na session that carries on afterwards.","operationId":"resolve_api_inbox__conversation_id__resolve_post","parameters":[{"in":"path","name":"conversation_id","required":true,"schema":{"format":"uuid","title":"Conversation Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Resolve","tags":["inbox"]}},"/api/integrations/{provider}/callback":{"get":{"description":"Completes any OAuth connection. Dispatches on the provider name.","operationId":"oauth_callback_api_integrations__provider__callback_get","parameters":[{"in":"path","name":"provider","required":true,"schema":{"title":"Provider","type":"string"}},{"in":"query","name":"code","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"}},{"in":"query","name":"state","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"in":"query","name":"error","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}}],"responses":{"200":{"content":{"application/json":{"schema":{}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Oauth Callback","tags":["integrations"]}},"/api/logs":{"get":{"description":"This workspace's API traffic, newest first.\n\nOnly requests authenticated with an API key appear here. The dashboard's\nown calls are not logged - they are not anybody's integration, and logging\nthem would bury the rows that are.\n\nMetadata only: no request or response bodies are recorded, ever. Retention\nfollows the plan, from one day on Free to a year on Enterprise.","operationId":"list_request_logs_api_logs_get","parameters":[{"in":"query","name":"limit","required":false,"schema":{"default":50,"maximum":200,"minimum":1,"title":"Limit","type":"integer"}},{"in":"query","name":"cursor","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"in":"query","name":"api_key_id","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key Id"}},{"description":"One of `2xx`, `3xx`, `4xx`, `5xx`, or `errors` for everything >= 400.","in":"query","name":"status_class","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"One of `2xx`, `3xx`, `4xx`, `5xx`, or `errors` for everything >= 400.","title":"Status Class"}},{"in":"query","name":"method","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Method"}},{"description":"Substring of the templated path, e.g. `bots` or `knowledge`.","in":"query","name":"path_contains","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Substring of the templated path, e.g. `bots` or `knowledge`.","title":"Path Contains"}},{"description":"The `X-Request-ID` from a response. This is the lookup to use when a customer quotes an error - it resolves to the exact call.","in":"query","name":"request_id","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The `X-Request-ID` from a response. This is the lookup to use when a customer quotes an error - it resolves to the exact call.","title":"Request Id"}},{"in":"query","name":"since_hours","required":false,"schema":{"anyOf":[{"maximum":2160,"minimum":1,"type":"integer"},{"type":"null"}],"title":"Since Hours"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response List Request Logs Api Logs Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Request Logs","tags":["dashboard"]}},"/api/logs/summary":{"get":{"description":"Volume, error rate, latency and the busiest endpoints over a window.\n\np95 rather than only a mean: a mean hides the case somebody is actually\ndebugging, which is a call that is usually fast and occasionally is not.","operationId":"request_log_summary_api_logs_summary_get","parameters":[{"in":"query","name":"hours","required":false,"schema":{"default":24,"maximum":2160,"minimum":1,"title":"Hours","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Request Log Summary Api Logs Summary Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Request Log Summary","tags":["dashboard"]}},"/api/notifications/preferences":{"get":{"description":"This user's toggles, with defaults filled in for anything unset.","operationId":"read_preferences_api_notifications_preferences_get","parameters":[{"in":"query","name":"org_id","required":false,"schema":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Org Id"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreferencesOut"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Read Preferences","tags":["notifications"]},"put":{"operationId":"write_preferences_api_notifications_preferences_put","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreferencesUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreferencesOut"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Write Preferences","tags":["notifications"]}},"/api/overview":{"get":{"description":"The dashboard home page: cross-bot totals plus plan usage.","operationId":"org_overview_api_overview_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Org Overview Api Overview Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Org Overview","tags":["dashboard"]}},"/api/preferences":{"get":{"operationId":"get_preferences_api_preferences_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Get Preferences Api Preferences Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Get Preferences","tags":["insights"]},"put":{"description":"Remembers which dashboard this person wants.\n\nPer user, not per organisation. Two people in one workspace routinely want\nopposite things - that is the whole premise of the two modes - and storing\nit on the org would make the last one to save win.","operationId":"set_preferences_api_preferences_put","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Payload","type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Set Preferences Api Preferences Put","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Set Preferences","tags":["insights"]}},"/api/report":{"get":{"description":"The organisation-wide report: every bot, rolled up, plus credits.","operationId":"org_report_api_report_get","parameters":[{"in":"query","name":"format","required":false,"schema":{"default":"html","pattern":"^(html|xlsx|pdf|csv|json)$","title":"Format","type":"string"}},{"in":"query","name":"days","required":false,"schema":{"default":30,"maximum":365,"minimum":1,"title":"Days","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Org Report","tags":["insights"]}},"/api/support":{"get":{"description":"This workspace's tickets.","operationId":"list_mine_api_support_get","parameters":[{"in":"query","name":"status","required":false,"schema":{"anyOf":[{"maxLength":20,"type":"string"},{"type":"null"}],"title":"Status"}},{"in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"title":"Page","type":"integer"}},{"in":"query","name":"page_size","required":false,"schema":{"default":20,"maximum":100,"minimum":1,"title":"Page Size","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response List Mine Api Support Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Mine","tags":["support"]},"post":{"description":"Raises a ticket.\n\nRate-limited per organisation rather than per user. The thing being\nprotected is the operator queue, and ten tickets from one workspace is the\nsame problem whether one person or five raised them.","operationId":"create_api_support_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketCreate"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Create Api Support Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Create","tags":["support"]}},"/api/support/categories":{"get":{"description":"The list a customer picks from, with what each one means.","operationId":"categories_api_support_categories_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Categories Api Support Categories Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Categories","tags":["support"]}},"/api/support/stats":{"get":{"operationId":"my_stats_api_support_stats_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response My Stats Api Support Stats Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"My Stats","tags":["support"]}},"/api/support/{ticket_id}":{"get":{"description":"One ticket and its thread. Internal notes are excluded by the query.","operationId":"get_one_api_support__ticket_id__get","parameters":[{"in":"path","name":"ticket_id","required":true,"schema":{"title":"Ticket Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Get One Api Support  Ticket Id  Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Get One","tags":["support"]}},"/api/support/{ticket_id}/close":{"post":{"description":"Lets the customer close their own ticket.\n\nWorth having: a customer who solved it themselves closing the ticket keeps\nthe operator queue honest, and the alternative is a queue full of things\nnobody needs any more.","operationId":"close_api_support__ticket_id__close_post","parameters":[{"in":"path","name":"ticket_id","required":true,"schema":{"title":"Ticket Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Close","tags":["support"]}},"/api/support/{ticket_id}/rate":{"post":{"description":"The customer's verdict, accepted only on a finished ticket.","operationId":"rate_api_support__ticket_id__rate_post","parameters":[{"in":"path","name":"ticket_id","required":true,"schema":{"title":"Ticket Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketRating"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Rate","tags":["support"]}},"/api/support/{ticket_id}/reply":{"post":{"description":"Adds a customer message.\n\nReopens a resolved ticket, which the service does in SQL. Somebody\nreplying to a closed ticket is telling us it was not resolved, and making\nthem raise a new one would lose the thread that explains why.","operationId":"reply_api_support__ticket_id__reply_post","parameters":[{"in":"path","name":"ticket_id","required":true,"schema":{"title":"Ticket Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketReply"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Reply Api Support  Ticket Id  Reply Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Reply","tags":["support"]}},"/api/tools":{"get":{"description":"Every tool in the organization, or the ones a given bot would be offered.\n\nWith `bot_id` the result is what that bot actually sees: its own tools plus\nthe org-wide ones. That is a different question from \"tools belonging to\nthis bot\", and it is the one worth answering, because it is what the model\nwill be handed.","operationId":"list_tools_api_tools_get","parameters":[{"in":"query","name":"bot_id","required":false,"schema":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Bot Id"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ToolResponse"},"title":"Response List Tools Api Tools Get","type":"array"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Tools","tags":["tools"]},"post":{"operationId":"create_tool_api_tools_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolCreate"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Create Tool","tags":["tools"]}},"/api/tools/{tool_id}":{"delete":{"operationId":"delete_tool_api_tools__tool_id__delete","parameters":[{"in":"path","name":"tool_id","required":true,"schema":{"format":"uuid","title":"Tool Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Delete Tool","tags":["tools"]},"get":{"operationId":"get_tool_api_tools__tool_id__get","parameters":[{"in":"path","name":"tool_id","required":true,"schema":{"format":"uuid","title":"Tool Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Get Tool","tags":["tools"]},"patch":{"operationId":"update_tool_api_tools__tool_id__patch","parameters":[{"in":"path","name":"tool_id","required":true,"schema":{"format":"uuid","title":"Tool Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Update Tool","tags":["tools"]}},"/api/tools/{tool_id}/calls":{"get":{"description":"What this tool has actually done, most recent first.\n\n`failed_only` is the triage path and is served by `ix_tool_calls_failures`,\nso it does not scan the successes - which are, on a working tool, nearly\nall of the rows.","operationId":"list_calls_api_tools__tool_id__calls_get","parameters":[{"in":"path","name":"tool_id","required":true,"schema":{"format":"uuid","title":"Tool Id","type":"string"}},{"in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"title":"Page","type":"integer"}},{"in":"query","name":"page_size","required":false,"schema":{"default":20,"maximum":100,"minimum":1,"title":"Page Size","type":"integer"}},{"in":"query","name":"failed_only","required":false,"schema":{"default":false,"title":"Failed Only","type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_ToolInvocationResponse_"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Calls","tags":["tools"]}},"/api/tools/{tool_id}/credential":{"get":{"description":"Confirms *which* credential is stored, without returning it.\n\nAt most four trailing characters, which is enough to tell \"the key I\nrotated last week\" from \"the key I rotated today\" and not enough to be\nworth anything to anyone who obtains it.","operationId":"credential_hint_api_tools__tool_id__credential_get","parameters":[{"in":"path","name":"tool_id","required":true,"schema":{"format":"uuid","title":"Tool Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Credential Hint","tags":["tools"]}},"/api/tools/{tool_id}/test":{"post":{"description":"Runs the tool once, exactly as a chat turn would.\n\nRate limited per organization: this endpoint makes an authenticated\noutbound request to an address the caller chose, so without a limit it is a\nrequest amplifier. The URL guard already decides *where* it may point; the\nlimit decides how often.","operationId":"test_tool_api_tools__tool_id__test_post","parameters":[{"in":"path","name":"tool_id","required":true,"schema":{"format":"uuid","title":"Tool Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolTestRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolTestResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Test Tool","tags":["tools"]}},"/api/usage":{"get":{"operationId":"usage_api_usage_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Usage Api Usage Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Usage","tags":["dashboard"]}},"/api/views":{"get":{"description":"Named filter sets for the conversation and contact lists.\n\nOrg-wide views come back alongside a bot's own, because a view scoped to\nthe organization is meant to be usable from every bot in it.","operationId":"list_saved_views_api_views_get","parameters":[{"in":"query","name":"resource","required":false,"schema":{"anyOf":[{"maxLength":32,"type":"string"},{"type":"null"}],"title":"Resource"}},{"in":"query","name":"bot_id","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bot Id"}}],"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response List Saved Views Api Views Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Saved Views","tags":["dashboard"]},"post":{"operationId":"create_saved_view_api_views_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedViewCreate"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Create Saved View Api Views Post","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Create Saved View","tags":["dashboard"]}},"/api/views/{view_id}":{"delete":{"operationId":"delete_saved_view_api_views__view_id__delete","parameters":[{"in":"path","name":"view_id","required":true,"schema":{"title":"View Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"204":{"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Delete Saved View","tags":["dashboard"]},"patch":{"operationId":"update_saved_view_api_views__view_id__patch","parameters":[{"in":"path","name":"view_id","required":true,"schema":{"title":"View Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedViewUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Update Saved View Api Views  View Id  Patch","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Update Saved View","tags":["dashboard"]}},"/api/webhooks":{"get":{"description":"Every endpoint in the workspace, or the ones a given bot's events reach.\n\nWith `bot_id` the answer includes org-wide endpoints, because the question\nbeing asked is \"where do this bot's events go\" - and an org-wide endpoint\nis one of the places they go.","operationId":"list_webhooks_api_webhooks_get","parameters":[{"in":"query","name":"bot_id","required":false,"schema":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Bot Id"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/WebhookResponse"},"title":"Response List Webhooks Api Webhooks Get","type":"array"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Webhooks","tags":["webhooks"]},"post":{"description":"Registers an endpoint and returns its signing secret, once.\n\nThe secret is in this response and nowhere else, ever. It can be rotated,\nnever read back - see the module docstring on `schemas`.","operationId":"create_webhook_api_webhooks_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreate"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreated"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Create Webhook","tags":["webhooks"]}},"/api/webhooks/deliveries":{"get":{"description":"Deliveries across every endpoint, newest first.\n\n`total` comes back as -1: this is a keyset-paginated log with no count, for\nthe reason given in `endpoint_service.list_deliveries`. Read `has_more`.\n\nThe payload is omitted from every row. Fifty deliveries carrying fifty\npayloads is a response nobody asked for; `GET /deliveries/{id}` has it.","operationId":"list_all_deliveries_api_webhooks_deliveries_get","parameters":[{"in":"query","name":"webhook_id","required":false,"schema":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"title":"Webhook Id"}},{"in":"query","name":"event","required":false,"schema":{"anyOf":[{"maxLength":64,"type":"string"},{"type":"null"}],"title":"Event"}},{"in":"query","name":"failed_only","required":false,"schema":{"default":false,"title":"Failed Only","type":"boolean"}},{"in":"query","name":"limit","required":false,"schema":{"default":20,"maximum":100,"minimum":1,"title":"Limit","type":"integer"}},{"in":"query","name":"cursor","required":false,"schema":{"anyOf":[{"maxLength":512,"type":"string"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_WebhookDeliveryResponse_"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List All Deliveries","tags":["webhooks"]}},"/api/webhooks/deliveries/{delivery_id}":{"get":{"description":"One delivery, with the payload that was actually sent.\n\nThe payload as *stored*, not as it would be regenerated - which is the\nwhole point when reconciling what a receiver got against what they expected.","operationId":"get_delivery_api_webhooks_deliveries__delivery_id__get","parameters":[{"in":"path","name":"delivery_id","required":true,"schema":{"format":"uuid","title":"Delivery Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Get Delivery","tags":["webhooks"]}},"/api/webhooks/deliveries/{delivery_id}/replay":{"post":{"description":"Re-sends a delivery as a new attempt that remembers the original.\n\nRate limited per workspace. A replay is an outbound request to an address\nthe caller chose, so without a ceiling the button is a request amplifier -\nthe same reasoning as the tools dry run.","operationId":"replay_delivery_api_webhooks_deliveries__delivery_id__replay_post","parameters":[{"in":"path","name":"delivery_id","required":true,"schema":{"format":"uuid","title":"Delivery Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Replay Delivery","tags":["webhooks"]}},"/api/webhooks/events":{"get":{"description":"The event catalogue, with a sample payload for each.\n\nDeclared before `/{webhook_id}` deliberately: FastAPI matches routes in\ndeclaration order, and a literal path registered after a parameterised one\nis shadowed by it - `events` would be parsed as a webhook id and answered\nwith a 422 about UUID format.","operationId":"list_events_api_webhooks_events_get","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/EventDescriptor"},"title":"Response List Events Api Webhooks Events Get","type":"array"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Events","tags":["webhooks"]}},"/api/webhooks/{webhook_id}":{"delete":{"operationId":"delete_webhook_api_webhooks__webhook_id__delete","parameters":[{"in":"path","name":"webhook_id","required":true,"schema":{"format":"uuid","title":"Webhook Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Delete Webhook","tags":["webhooks"]},"get":{"operationId":"get_webhook_api_webhooks__webhook_id__get","parameters":[{"in":"path","name":"webhook_id","required":true,"schema":{"format":"uuid","title":"Webhook Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Get Webhook","tags":["webhooks"]},"patch":{"description":"Changes URL, events, description or active state.\n\nSetting `is_active: true` on an endpoint the platform auto-disabled also\nclears its failure counter - otherwise it re-disables on the first hiccup\nand the button looks broken.","operationId":"update_webhook_api_webhooks__webhook_id__patch","parameters":[{"in":"path","name":"webhook_id","required":true,"schema":{"format":"uuid","title":"Webhook Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Update Webhook","tags":["webhooks"]}},"/api/webhooks/{webhook_id}/rotate-secret":{"post":{"description":"Issues a new signing secret. The old one stops working immediately.\n\nThere is no overlap window. Deliveries signed with the new secret start on\nthe next event, so update the receiver before calling this or plan for a\nshort window of signature failures - which the delivery log will show, and\nwhich retries will clear once the receiver is updated.","operationId":"rotate_secret_api_webhooks__webhook_id__rotate_secret_post","parameters":[{"in":"path","name":"webhook_id","required":true,"schema":{"format":"uuid","title":"Webhook Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateSecretResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Rotate Secret","tags":["webhooks"]}},"/api/webhooks/{webhook_id}/test":{"post":{"description":"Fires a synthetic event down the real delivery path.\n\nReturns as soon as the delivery is queued - `202`-shaped behaviour with a\n`200`, because the result is a row the caller then polls for rather than\nsomething this request can wait on. Posting inline would be faster and\nwould skip the queue, the retry classification and the failure accounting,\nso a test could pass on an endpoint every real delivery fails against.\n\nThe payload carries `\"test\": true` at the top level. A test event that a\nreceiver cannot distinguish from a real one is a test that creates a real\nrecord in somebody's CRM.","operationId":"test_webhook_api_webhooks__webhook_id__test_post","parameters":[{"in":"path","name":"webhook_id","required":true,"schema":{"format":"uuid","title":"Webhook Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTestRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTestResponse"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Test Webhook","tags":["webhooks"]}},"/api/workspace":{"get":{"operationId":"current_workspace_api_workspace_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Current Workspace Api Workspace Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Current Workspace","tags":["workspace"]},"patch":{"operationId":"update_workspace_api_workspace_patch","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Update Workspace Api Workspace Patch","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Update Workspace","tags":["workspace"]}},"/api/workspace/encryption":{"get":{"description":"What this workspace encrypts, and what that costs.\n\nOwner-only. Not because reading it is dangerous, but because the answer is\na security posture statement about the whole workspace and the people who\nshould see it are the people who can change it.","operationId":"read_encryption_api_workspace_encryption_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EncryptionState"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Read Encryption","tags":["workspace"]},"put":{"description":"Turns tenant-scoped encryption on or off.\n\nBoth directions are safe and neither is instant.\n\n**On** takes effect immediately for new writes once a key exists, and the\n`crypto.seal_backlog` sweep converts what came before. Nothing becomes\nunreadable in the meantime: a plaintext value opens as itself.\n\n**Off** stops new writes being sealed and leaves existing ciphertext\nsealed, which keeps reading correctly because the key is still there. It\ndoes not decrypt anything, and saying otherwise would be the dangerous\nlie - a customer who switches off, exports, and deletes their workspace\nwould otherwise expect plaintext they never got.","operationId":"set_encryption_api_workspace_encryption_put","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EncryptionUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EncryptionState"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Set Encryption","tags":["workspace"]}},"/api/workspace/hierarchy":{"get":{"description":"This workspace and everything beneath it.","operationId":"workspace_hierarchy_api_workspace_hierarchy_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HierarchyNode"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Workspace Hierarchy","tags":["workspace"]}},"/api/workspace/invitations":{"get":{"operationId":"list_invitations_api_workspace_invitations_get","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/InvitationRead"},"title":"Response List Invitations Api Workspace Invitations Get","type":"array"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Invitations","tags":["workspace"]},"post":{"description":"Invites somebody into this workspace.\n\nThe role travels in the invitation, not in the acceptance - see\n`invitation_service` for why that is the whole security of the flow.\n\nThe email is queued inside the same transaction as the invitation row, so\nthe two commit together. An invitation stored without its email is a person\nwho never hears from us; an email sent for a row that rolled back is a link\nthat does not work.","operationId":"create_invitation_api_workspace_invitations_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationCreate"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationRead"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Create Invitation","tags":["workspace"]}},"/api/workspace/invitations/{invitation_id}":{"delete":{"description":"Cancels a pending invitation.\n\nThe link stops working immediately, which is the point: an invitation sent\nto the wrong address must be recallable, and \"it expires in a week\" is not\nan answer to that.","operationId":"revoke_invitation_api_workspace_invitations__invitation_id__delete","parameters":[{"in":"path","name":"invitation_id","required":true,"schema":{"title":"Invitation Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Revoke Invitation","tags":["workspace"]}},"/api/workspace/members":{"get":{"operationId":"list_members_api_workspace_members_get","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/MemberRead"},"title":"Response List Members Api Workspace Members Get","type":"array"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Members","tags":["workspace"]}},"/api/workspace/members/{user_id}":{"delete":{"operationId":"remove_member_api_workspace_members__user_id__delete","parameters":[{"in":"path","name":"user_id","required":true,"schema":{"title":"User Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Remove Member","tags":["workspace"]},"patch":{"operationId":"change_member_role_api_workspace_members__user_id__patch","parameters":[{"in":"path","name":"user_id","required":true,"schema":{"title":"User Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberRoleUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Change Member Role","tags":["workspace"]}},"/api/workspace/sub-accounts":{"get":{"operationId":"list_sub_accounts_api_workspace_sub_accounts_get","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SubAccountRead"},"title":"Response List Sub Accounts Api Workspace Sub Accounts Get","type":"array"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"List Sub Accounts","tags":["workspace"]},"post":{"description":"Opens a workspace for a client, beneath this one.\n\nNobody is added to it. The client gets access by accepting an invitation;\nuntil then the agency administers it through this workspace. See\n`app/domains/tenancy/service.py` for why a membership would be the wrong\nmechanism.","operationId":"create_sub_account_api_workspace_sub_accounts_post","parameters":[{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubAccountCreate"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubAccountRead"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Create Sub Account","tags":["workspace"]}},"/api/workspace/sub-accounts/{sub_account_id}":{"delete":{"operationId":"delete_sub_account_api_workspace_sub_accounts__sub_account_id__delete","parameters":[{"in":"path","name":"sub_account_id","required":true,"schema":{"title":"Sub Account Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Delete Sub Account","tags":["workspace"]},"patch":{"operationId":"update_sub_account_api_workspace_sub_accounts__sub_account_id__patch","parameters":[{"in":"path","name":"sub_account_id","required":true,"schema":{"title":"Sub Account Id","type":"string"}},{"description":"A unique key of your choosing, so this request can be retried safely. The first request with a given key executes; every replay returns that first response unchanged, with `Idempotent-Replay: true` set.\n\nGenerate one key per *action*, not per session - reusing a key with a different body is refused with 422 rather than silently replaying the wrong answer. Keys are remembered for 24 hours. A request that failed releases its key, so a retry after fixing the payload runs normally.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubAccountRead"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}},"description":"Validation Error","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"security":[{"HTTPBearer":[]}],"summary":"Update Sub Account","tags":["workspace"]}},"/health":{"get":{"description":"Liveness. Answers without touching any dependency, so a database\nblip does not cause the orchestrator to kill a healthy process.","operationId":"health_health_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Health Health Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Health","tags":["health"]}},"/health/ready":{"get":{"description":"Readiness. Checks the dependencies a request actually needs, so a\nload balancer stops sending traffic to an instance that cannot serve.","operationId":"readiness_health_ready_get","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":true,"title":"Response Readiness Health Ready Get","type":"object"}}},"description":"Successful Response","headers":{"RateLimit-Limit":{"description":"Requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the current window. Back off before it reaches 0.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"}},"X-API-Version":{"description":"The dated version of the API contract that served this response, e.g. `2026-09-03`. Pin against it; it changes only when a response shape changes incompatibly.","schema":{"type":"string"}},"X-Request-ID":{"description":"Quote this in a support request to identify the call.","schema":{"type":"string"}}}}},"summary":"Readiness","tags":["health"]}}},"servers":[{"url":"https://api.integrable.cloud","description":"Production"}]}