{"openapi":"3.1.0","info":{"title":"Clement API","version":"0.0.0","description":"Clement public API. See clement.so/docs for guides; this spec is the canonical reference."},"servers":[{"url":"https://api.clement.so","description":"Production"}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"API Key (cl_live_… / cl_test_…)"}},"schemas":{"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"service":{"type":"string","enum":["api"]},"version":{"type":"string"}},"required":["status","service","version"]},"ApiKey":{"type":"object","properties":{"id":{"type":"string","example":"key_AM788072KD0X99RP8HK5AH0000"},"object":{"type":"string","enum":["api_key"]},"name":{"type":"string"},"mode":{"type":"string","enum":["live","test"]},"scope":{"type":"string","enum":["read","write","admin"]},"last_four":{"type":"string","minLength":4,"maxLength":4},"auto_confirm":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"},"revoked_at":{"type":["string","null"],"format":"date-time"}},"required":["id","object","name","mode","scope","last_four","auto_confirm","created_at","last_used_at","revoked_at"],"example":{"id":"key_01HZ8X3J9K7P2QV6R5N4M3T2LC","object":"api_key","name":"Production CRM sync","mode":"live","scope":"write","last_four":"x4Y9","auto_confirm":false,"created_at":"2026-04-15T09:00:00Z","last_used_at":"2026-04-29T15:42:00Z","revoked_at":null}},"ApiKeyList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor"]},"ErrorEnvelope":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"param":{"type":"string"},"request_id":{"type":"string"},"doc_url":{"type":"string","format":"uri"}},"required":["type","code","message"]}},"required":["error"]},"ApiKeyWithSecret":{"allOf":[{"$ref":"#/components/schemas/ApiKey"},{"type":"object","properties":{"secret":{"type":"string","example":"cl_live_a1b2c3d4e5f6…"}},"required":["secret"]}],"example":{"id":"key_01HZ8X3J9K7P2QV6R5N4M3T2LC","object":"api_key","name":"Production CRM sync","mode":"live","scope":"write","last_four":"x4Y9","auto_confirm":false,"created_at":"2026-04-15T09:00:00Z","last_used_at":"2026-04-29T15:42:00Z","revoked_at":null}},"ApiKeyCreate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"scope":{"type":"string","enum":["read","write","admin"],"default":"write"},"mode":{"type":"string","enum":["live","test"],"description":"Defaults to the calling key's mode. An API key may only create keys of its own mode (403 otherwise); dashboard sessions may create either, defaulting to `live`."},"auto_confirm":{"type":"boolean","default":false}},"required":["name"]},"InboxRamp":{"type":"object","properties":{"enabled":{"type":"boolean"},"start":{"type":"integer","description":"Cap on day 0 of the ramp."},"end":{"type":"integer","description":"Cap once the ramp completes (never above `daily_limit`)."},"days":{"type":"integer","description":"Days to go from `start` to `end`."},"started_at":{"type":"string","format":"date-time","description":"Day 0 of the ramp (the connect time unless ramp-up was turned on later)."}},"required":["enabled","start","end","days","started_at"]},"SandboxConfig":{"type":["object","null"],"properties":{"open_probability":{"type":"number","minimum":0,"maximum":1},"click_probability":{"type":"number","minimum":0,"maximum":1},"reply_probability":{"type":"number","minimum":0,"maximum":1},"bounce_probability":{"type":"number","minimum":0,"maximum":1},"open_delay_seconds_min":{"type":"integer","minimum":0},"open_delay_seconds_max":{"type":"integer","minimum":0},"click_delay_seconds_min":{"type":"integer","minimum":0},"click_delay_seconds_max":{"type":"integer","minimum":0},"reply_delay_seconds_min":{"type":"integer","minimum":0},"reply_delay_seconds_max":{"type":"integer","minimum":0}},"required":["open_probability","click_probability","reply_probability","bounce_probability","open_delay_seconds_min","open_delay_seconds_max","click_delay_seconds_min","click_delay_seconds_max","reply_delay_seconds_min","reply_delay_seconds_max"],"description":"Populated only for `provider: 'sandbox'` inboxes; null otherwise."},"Inbox":{"type":"object","properties":{"id":{"type":"string","example":"inb_AM788072KD0X99RP8HK5AH0000"},"object":{"type":"string","enum":["inbox"]},"mode":{"type":"string","enum":["live","test"],"description":"`live` for real-provider inboxes; `test` for sandbox inboxes."},"provider":{"type":"string","example":"gmail"},"email_address":{"type":"string","format":"email"},"display_name":{"type":["string","null"]},"status":{"type":"string","enum":["connecting","active","token_expired","revoked","over_quota_today","unhealthy","paused","failed"]},"status_reason":{"type":["string","null"]},"daily_limit":{"type":"integer","description":"Target maximum sends per day (inbox timezone). The ramp climbs toward it."},"effective_daily_limit":{"type":"integer","description":"Today's actual cap: `daily_limit`, or the ramp's value for today if lower."},"ramp":{"$ref":"#/components/schemas/InboxRamp"},"signature_html":{"type":["string","null"],"description":"Appended to campaign sends, and to API sends / replies with `append_signature`."},"signature_text":{"type":["string","null"],"description":"Plain-text version of `signature_html`, derived on save."},"reply_to":{"type":["string","null"],"description":"Reply-To header on outgoing mail. null = replies go to `email_address`. Reply detection only sees inboxes connected to this workspace: a Reply-To outside them means replies aren't detected and sequences don't stop on reply."},"tags":{"type":"array","items":{"type":"string"},"description":"Workspace-scoped labels. Campaigns can pick senders by tag."},"health_score":{"type":["integer","null"],"description":"0–100, null until first compute"},"warmup_enabled":{"type":"boolean"},"timezone":{"type":"string","example":"Europe/Berlin"},"last_send_at":{"type":["string","null"],"format":"date-time"},"last_poll_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"revoked_at":{"type":["string","null"],"format":"date-time"},"sandbox_config":{"$ref":"#/components/schemas/SandboxConfig"}},"required":["id","object","mode","provider","email_address","display_name","status","status_reason","daily_limit","effective_daily_limit","ramp","signature_html","signature_text","reply_to","tags","health_score","warmup_enabled","timezone","last_send_at","last_poll_at","created_at","revoked_at","sandbox_config"],"example":{"id":"inb_01HZ8X3J9K7P2QV6R5N4M3T2L1","object":"inbox","mode":"live","provider":"gmail","email_address":"founder@acme.com","display_name":"Alice from Acme","status":"active","status_reason":null,"daily_limit":50,"effective_daily_limit":26,"ramp":{"enabled":true,"start":10,"end":50,"days":14,"started_at":"2026-04-22T09:00:00Z"},"signature_html":"<p>Alice<br>Acme</p>","signature_text":"Alice\nAcme","reply_to":null,"tags":["outbound","eu"],"health_score":92,"warmup_enabled":true,"timezone":"America/New_York","last_send_at":"2026-04-29T14:32:11Z","last_poll_at":"2026-04-29T15:00:04Z","created_at":"2026-04-15T09:12:00Z","revoked_at":null,"sandbox_config":null}},"InboxList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Inbox"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor","prev_cursor"]},"InboxGoogleConnectLink":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"One-time URL the customer/agent visits in a browser to OAuth-connect a Gmail inbox. The token in the URL expires after 1 hour."},"expires_at":{"type":"string","format":"date-time"}},"required":["url","expires_at"]},"InboxGoogleConnectLinkCreate":{"type":"object","properties":{"redirect_url":{"type":"string","format":"uri","description":"Where the dashboard sends the visitor after the OAuth callback completes. Must be `https://` and is only honored on the app's own origin (app.clement.so); any other origin falls back to the default, `/dashboard/inboxes`."}}},"InboxSmtpServer":{"type":"object","properties":{"host":{"type":"string","minLength":1,"maxLength":253,"example":"smtp.example.com"},"port":{"type":"integer","minimum":1,"maximum":65535,"example":465},"security":{"type":"string","enum":["ssl","starttls"],"description":"`ssl` = implicit TLS (465 / 993); `starttls` = upgrade on a plain port (587 / 143)."},"username":{"type":"string","minLength":1,"maxLength":320,"description":"Login. Defaults to `email_address`."},"password":{"type":"string","minLength":1,"maxLength":1024,"description":"Password or app password. Stored encrypted; never returned."}},"required":["host","port","security","password"]},"InboxImapServer":{"type":"object","properties":{"host":{"type":"string","minLength":1,"maxLength":253,"example":"smtp.example.com"},"port":{"type":"integer","minimum":1,"maximum":65535,"example":465},"security":{"type":"string","enum":["ssl","starttls"],"description":"`ssl` = implicit TLS (465 / 993); `starttls` = upgrade on a plain port (587 / 143)."},"username":{"type":"string","minLength":1,"maxLength":320,"description":"Defaults to the SMTP username."},"password":{"type":"string","minLength":1,"maxLength":1024,"description":"Defaults to the SMTP password."}},"required":["host","port","security"]},"InboxSmtpCreate":{"type":"object","properties":{"email_address":{"type":"string","format":"email","example":"alex@acme.com"},"display_name":{"type":"string","maxLength":120},"smtp":{"$ref":"#/components/schemas/InboxSmtpServer"},"imap":{"$ref":"#/components/schemas/InboxImapServer"}},"required":["email_address","smtp","imap"],"example":{"email_address":"alex@acme.com","display_name":"Alex from Acme","smtp":{"host":"smtp.zoho.com","port":465,"security":"ssl","username":"alex@acme.com","password":"app-password"},"imap":{"host":"imap.zoho.com","port":993,"security":"ssl"}}},"InboxSandboxCreate":{"type":"object","properties":{"email_address":{"type":"string","format":"email","description":"Optional. Synthetic email used to render the sandbox in lists and as the From address on synthetic outbound messages. Auto-generated as `sandbox-<short>@sandbox.clement.so` when omitted."},"display_name":{"type":"string","maxLength":120},"sandbox_config":{"allOf":[{"$ref":"#/components/schemas/SandboxConfig"},{"type":"object","description":"Behavior knobs for the synthetic event generator. Partial — unspecified fields take the workspace defaults."}]}}},"InboxSandboxPatch":{"type":"object","properties":{"display_name":{"type":["string","null"],"maxLength":120,"description":"Sender name shown in the From header. null clears it."},"status":{"type":"string","enum":["active","paused"],"description":"Only `active` ↔ `paused` transitions are allowed via PATCH, and only from `active` or `paused`."},"daily_limit":{"type":"integer","minimum":1,"maximum":500,"description":"Target maximum sends per inbox day (1–500)."},"ramp":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Turning ramp-up on restarts it today."},"start":{"type":"integer","minimum":1,"maximum":500},"end":{"type":"integer","minimum":1,"maximum":500},"days":{"type":"integer","minimum":1,"maximum":90}},"description":"Linear ramp from `start` to `end` over `days`, capped by `daily_limit`. Partial: unspecified fields keep their value."},"signature_html":{"type":["string","null"],"maxLength":10000,"description":"HTML signature. Scripts and event handlers are stripped; `signature_text` is derived. null or empty clears it."},"reply_to":{"type":["string","null"],"format":"email","description":"Reply-To address for outgoing mail. null clears it. Use another inbox connected to this workspace: replies to an address Clement doesn't poll aren't detected, so sequences won't stop on reply."},"timezone":{"type":"string","description":"IANA timezone (e.g. `Europe/Berlin`); defines the inbox's sending day.","example":"Europe/Berlin"},"tags":{"type":"array","items":{"type":"string","maxLength":40},"maxItems":20,"description":"Replaces the inbox's tags. Normalized to lowercase; letters, digits, spaces and - _ . / : only."},"warmup_enabled":{"type":"boolean","description":"Gmail inboxes only. Joins or leaves the warmup pool; joining restarts the warmup ramp. Needs a paid plan (not during the trial)."},"sandbox_config":{"allOf":[{"$ref":"#/components/schemas/SandboxConfig"},{"type":"object","description":"Sandbox inboxes only. Merged into the existing config; unspecified fields keep their current value."}]}}},"SendExpandInbox":{"type":["object","null"],"properties":{"id":{"type":"string"},"email_address":{"type":"string","format":"email"},"display_name":{"type":["string","null"]},"status":{"type":"string"}},"required":["id","email_address","display_name","status"],"description":"Present (possibly null if missing) when `?expand=inbox`."},"Send":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["send"]},"mode":{"type":"string","enum":["live","test"]},"inbox_id":{"type":"string"},"inbox":{"$ref":"#/components/schemas/SendExpandInbox"},"to_email":{"type":"string","format":"email"},"subject":{"type":"string"},"state":{"type":"string","enum":["scheduled","sending","sent","failed"]},"failure_reason":{"type":["string","null"]},"provider_message_id":{"type":["string","null"]},"provider_thread_id":{"type":["string","null"]},"rfc822_message_id":{"type":["string","null"]},"attempt_count":{"type":"integer"},"scheduled_at":{"type":"string","format":"date-time"},"sent_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"campaign_id":{"type":["string","null"]}},"required":["id","object","mode","inbox_id","to_email","subject","state","failure_reason","provider_message_id","provider_thread_id","rfc822_message_id","attempt_count","scheduled_at","sent_at","created_at","campaign_id"],"example":{"id":"snd_01HZ8X3J9K7P2QV6R5N4M3T2L4","object":"send","mode":"live","inbox_id":"inb_01HZ8X3J9K7P2QV6R5N4M3T2L1","to_email":"alice@example.com","subject":"Quick question about Acme's data stack","state":"sent","failure_reason":null,"provider_message_id":"18f8a2b...","provider_thread_id":"18f8a2b...","rfc822_message_id":"<01HZ8X3J9K7P2QV6@mail.clement.so>","attempt_count":1,"scheduled_at":"2026-04-29T14:30:00Z","sent_at":"2026-04-29T14:30:02Z","created_at":"2026-04-29T14:30:00Z","campaign_id":null}},"BulkSendResult":{"type":"object","properties":{"object":{"type":"string","enum":["bulk_send_result"]},"created":{"type":"array","items":{"$ref":"#/components/schemas/Send"}},"errors":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"recipient":{"type":"string"},"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["type","code","message"]}},"required":["index","recipient","error"]}}},"required":["object","created","errors"]},"SendFromStrategy":{"type":"object","properties":{"type":{"type":"string","enum":["single","rotate","least_busy"]},"inbox_id":{"type":"string"},"inbox_ids":{"type":"array","items":{"type":"string"}}},"required":["type"]},"SendCreate":{"type":"object","properties":{"inbox_id":{"type":"string","description":"Single-inbox shorthand. Equivalent to `from_strategy: { type: 'single', inbox_id }`."},"from_strategy":{"$ref":"#/components/schemas/SendFromStrategy"},"to":{"anyOf":[{"type":"string","format":"email"},{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string"}},"required":["email"]},{"type":"array","items":{"anyOf":[{"type":"string","format":"email"},{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string"}},"required":["email"]}]},"minItems":1,"maxItems":1000}]},"subject":{"type":"string","minLength":1},"body_html":{"type":"string"},"body_text":{"type":"string"},"variables":{"type":"object","additionalProperties":{}},"send_at":{"type":["string","null"],"format":"date-time","description":"RFC-3339 timestamp; null/omitted = enqueue immediately."},"thread_id":{"type":"string","description":"Public thread id (`thr_…`). Setting this turns the send into a reply in that thread: it must be sent from the thread's inbox (`inbox_id` or a `single` from_strategy), and `In-Reply-To` defaults to the thread's latest message."},"in_reply_to_message_id":{"type":"string","description":"RFC 822 Message-ID (`<…@…>`) to cite in `In-Reply-To`. With `thread_id`, overrides the default (the thread's latest message)."},"metadata":{"type":"object","additionalProperties":{"type":"string"},"description":"Customer-supplied dict echoed back on every event for this send."},"append_signature":{"type":"boolean","description":"Append the sending inbox's signature (`signature_html` / `signature_text`) to the body parts you supply. Default false: ad-hoc sends go out exactly as written."}},"required":["to","subject"]},"SendList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Send"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor","prev_cursor"]},"MessageExpandInbox":{"type":["object","null"],"properties":{"id":{"type":"string"},"email_address":{"type":"string","format":"email"},"display_name":{"type":["string","null"]},"status":{"type":"string"}},"required":["id","email_address","display_name","status"]},"Message":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["message"]},"mode":{"type":"string","enum":["live","test"]},"inbox_id":{"type":"string"},"inbox":{"$ref":"#/components/schemas/MessageExpandInbox"},"direction":{"type":"string","enum":["inbound","outbound"]},"classification":{"type":["string","null"],"enum":["reply","auto_reply","bounce","unrelated"]},"thread_id":{"type":"string","description":"Provider thread id (Gmail's resource id)"},"rfc822_message_id":{"type":["string","null"]},"in_reply_to":{"type":["string","null"]},"from_email":{"type":["string","null"]},"from_name":{"type":["string","null"]},"subject":{"type":["string","null"]},"bounce_type":{"type":["string","null"]},"bounce_status_code":{"type":["string","null"]},"matched_send_id":{"type":["string","null"]},"received_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}},"required":["id","object","mode","inbox_id","direction","classification","thread_id","rfc822_message_id","in_reply_to","from_email","from_name","subject","bounce_type","bounce_status_code","matched_send_id","received_at","created_at"],"example":{"id":"msg_01HZ8X3J9K7P2QV6R5N4M3T2L5","object":"message","mode":"live","inbox_id":"inb_01HZ8X3J9K7P2QV6R5N4M3T2L1","direction":"inbound","classification":"reply","thread_id":"18f8a2b3c4d5e6f","rfc822_message_id":"<reply-abc123@example.com>","in_reply_to":"<01HZ8X3J9K7P2QV6@mail.clement.so>","from_email":"alice@example.com","from_name":"Alice","subject":"Re: Quick question about Acme's data stack","bounce_type":null,"bounce_status_code":null,"matched_send_id":"snd_01HZ8X3J9K7P2QV6R5N4M3T2L4","received_at":"2026-04-29T16:42:11Z","created_at":"2026-04-29T16:42:13Z"}},"MessageList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Message"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor","prev_cursor"]},"MessageBody":{"type":"object","properties":{"object":{"type":"string","enum":["message_body"]},"message_id":{"type":"string"},"html":{"type":["string","null"]},"text":{"type":["string","null"]}},"required":["object","message_id","html","text"]},"Contact":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["contact"]},"mode":{"type":"string","enum":["live","test"]},"email":{"type":"string","format":"email"},"attributes":{"type":"object","additionalProperties":{}},"global_status":{"type":"string","enum":["ok","unsubscribed","bounced","blacklisted"]},"lead_status":{"type":["string","null"],"enum":["interested","meeting_booked","not_interested"],"description":"Read-only here; set with POST /v1/contacts/{id}/lead_status. The workflow tag a member gave the lead after a reply. Stored as `attributes.lead_classification`."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","object","mode","email","attributes","global_status","lead_status","created_at","updated_at"],"example":{"id":"con_01HZ8X3J9K7P2QV6R5N4M3T2L2","object":"contact","mode":"live","email":"alice@example.com","attributes":{"first_name":"Alice","company":"Acme","title":"VP Eng"},"global_status":"ok","lead_status":null,"created_at":"2026-04-20T10:14:00Z","updated_at":"2026-04-20T10:14:00Z"}},"ContactList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Contact"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor","prev_cursor"]},"ContactCreate":{"type":"object","properties":{"email":{"type":"string","format":"email"},"attributes":{"type":"object","additionalProperties":{}},"global_status":{"type":"string","enum":["ok","unsubscribed","bounced","blacklisted"]}},"required":["email"]},"ContactPatch":{"type":"object","properties":{"attributes":{"type":"object","additionalProperties":{},"description":"Merged into existing attributes. Set a key to `null` to remove it from the contact."},"global_status":{"type":"string","enum":["ok","unsubscribed","bounced","blacklisted"]}}},"ContactBatchResult":{"type":"object","properties":{"object":{"type":"string","enum":["batch_result"]},"created":{"type":"array","items":{"$ref":"#/components/schemas/Contact"}},"errors":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"email":{"type":"string"},"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["type","code","message"]}},"required":["index","email","error"]}}},"required":["object","created","errors"]},"ContactBatch":{"type":"object","properties":{"contacts":{"type":"array","items":{"$ref":"#/components/schemas/ContactCreate"},"minItems":1,"maxItems":1000}},"required":["contacts"]},"ContactImport":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["contact_import"]},"mode":{"type":"string","enum":["live","test"]},"status":{"type":"string","enum":["queued","processing","succeeded","failed"]},"total_rows":{"type":"integer"},"succeeded_rows":{"type":"integer"},"failed_rows":{"type":"integer"},"errors":{"type":"array","items":{"type":"object","properties":{"row":{"type":"integer"},"email":{"type":["string","null"]},"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["type","code","message"]}},"required":["row","email","error"]}},"audience_id":{"type":["string","null"]},"audience_created":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"started_at":{"type":["string","null"],"format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"}},"required":["id","object","mode","status","total_rows","succeeded_rows","failed_rows","errors","audience_id","audience_created","created_at","started_at","completed_at"],"example":{"id":"imp_01HZ8X3J9K7P2QV6R5N4M3T2LE","object":"contact_import","mode":"live","status":"succeeded","total_rows":1850,"succeeded_rows":1842,"failed_rows":8,"errors":[{"row":17,"email":"not-an-email","error":{"type":"invalid_request_error","code":"invalid_email","message":"Email is missing or malformed"}}],"audience_id":"aud_01HZ8X3J9K7P2QV6R5N4M3T2L3","audience_created":false,"created_at":"2026-05-02T16:00:00Z","started_at":"2026-05-02T16:00:01Z","completed_at":"2026-05-02T16:00:43Z"}},"ContactImportList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/ContactImport"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor","prev_cursor"]},"ContactImportDryRun":{"type":"object","properties":{"id":{"type":"string","example":"dryrun_a1b2c3d4"},"object":{"type":"string","enum":["contact_import_dry_run"]},"mode":{"type":"string","enum":["live","test"]},"total_rows":{"type":"integer"},"valid_rows":{"type":"integer","description":"Rows that would be upserted on a real run. Duplicates within the file are excluded; existing-email upserts are still counted (they'd no-op)."},"invalid_rows":{"type":"integer"},"errors":{"type":"array","items":{"type":"object","properties":{"row":{"type":"integer"},"email":{"type":["string","null"]},"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["type","code","message"]}},"required":["row","email","error"]}}},"required":["id","object","mode","total_rows","valid_rows","invalid_rows","errors"]},"ContactImportCreate":{"type":"object","properties":{"file":{"type":"string","description":"CSV file. First row is the header; subsequent rows are contacts.","format":"binary"},"column_map":{"type":"string","description":"JSON object mapping CSV column header → contact attribute. Special target `email` (required) maps the column whose value is the contact's email address. All other columns become attributes. Example: `{\"Email\":\"email\",\"First Name\":\"first_name\",\"Company\":\"company\"}`."},"audience_id":{"type":"string","description":"Attach the imported contacts to this existing audience."},"audience_name":{"type":"string","description":"Auto-create an audience with this name and attach the imported contacts to it. Mutually exclusive with `audience_id`."}},"required":["column_map"]},"Audience":{"type":"object","properties":{"id":{"type":"string","example":"aud_AM788072KD0X99RP8HK5AH0000"},"object":{"type":"string","enum":["audience"]},"mode":{"type":"string","enum":["live","test"]},"name":{"type":"string"},"description":{"type":["string","null"]},"contact_count":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","object","mode","name","description","contact_count","created_at","updated_at"],"example":{"id":"aud_01HZ8X3J9K7P2QV6R5N4M3T2L3","object":"audience","mode":"live","name":"Q2 outbound prospects","description":"Pulled from HubSpot \"Tier 1\" segment, May import.","contact_count":1842,"created_at":"2026-05-02T16:00:00Z","updated_at":"2026-05-02T16:00:00Z"}},"AudienceList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Audience"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor","prev_cursor"]},"AudienceCreate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":1000}},"required":["name"]},"AudiencePatch":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":["string","null"],"maxLength":1000}}},"AudienceAttachResult":{"type":"object","properties":{"object":{"type":"string","enum":["attach_result"]},"attached":{"type":"integer"},"skipped":{"type":"integer"},"errors":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"contact_id":{"type":"string"},"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["type","code","message"]}},"required":["index","contact_id","error"]}}},"required":["object","attached","skipped","errors"]},"AudienceAttachContacts":{"type":"object","properties":{"contact_ids":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":1000}},"required":["contact_ids"]},"SequenceStepVariant":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"subject":{"type":"string","maxLength":998,"description":"May be blank (or omitted) on a follow-up step: the email then goes out in the same thread as `Re: <subject of the previous email>`. The first step needs one."},"body_html":{"type":"string"},"body_text":{"type":"string"},"disabled":{"type":"boolean","description":"Kept (with its stats) but out of the distribution. At least one must stay enabled."}},"required":["id","subject","body_html","body_text"]},"SequenceStepStandalone":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["sequence_step"]},"sequence_id":{"type":"string"},"step_order":{"type":"integer"},"delay_days":{"type":"integer"},"delay_minutes":{"type":"integer","description":"Wait after the previous step, in minutes (authoritative over `delay_days`)."},"subject":{"type":"string"},"body_html":{"type":"string"},"body_text":{"type":"string"},"variants":{"type":["array","null"],"items":{"$ref":"#/components/schemas/SequenceStepVariant"}},"winning_variant_id":{"type":["string","null"]}},"required":["id","object","sequence_id","step_order","delay_days","delay_minutes","subject","body_html","body_text","variants","winning_variant_id"]},"Sequence":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["sequence"]},"mode":{"type":"string","enum":["live","test"]},"name":{"type":"string"},"description":{"type":["string","null"]},"step_count":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/SequenceStepStandalone"},"description":"Embedded on retrieve. Omitted from list responses."}},"required":["id","object","mode","name","description","step_count","created_at","updated_at"],"example":{"id":"seq_01HZ8X3J9K7P2QV6R5N4M3T2L6","object":"sequence","mode":"live","name":"Q2 outbound — 3 steps","description":"Cold intro → 3-day follow-up → 7-day breakup","step_count":3,"created_at":"2026-04-25T10:00:00Z","updated_at":"2026-04-25T10:00:00Z"}},"SequenceList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Sequence"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor","prev_cursor"]},"SequenceCreate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":1000},"steps":{"type":"array","items":{"type":"object","properties":{"step_order":{"type":"integer","minimum":0,"description":"0-based position. Omit to append; an existing position inserts before that step."},"delay_days":{"type":"integer","minimum":0,"maximum":365,"description":"Wait in whole days. Prefer `delay_minutes`."},"delay_minutes":{"type":"integer","minimum":0,"maximum":525600,"description":"Wait after the previous step's send, in minutes (sends still respect the campaign's schedule window). Takes precedence over `delay_days`."},"subject":{"type":"string","maxLength":998,"description":"May be blank (or omitted) on a follow-up step: the email then goes out in the same thread as `Re: <subject of the previous email>`. The first step needs one."},"body_html":{"type":"string"},"body_text":{"type":"string"},"variants":{"type":"array","items":{"$ref":"#/components/schemas/SequenceStepVariant"},"maxItems":10},"winning_variant_id":{"type":"string"}}},"minItems":1,"maxItems":50,"description":"Optional initial steps. Add later via POST /v1/sequences/{id}/steps."}},"required":["name"]},"SequencePatch":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":["string","null"],"maxLength":1000}}},"SequenceStepPatch":{"type":"object","properties":{"step_order":{"type":"integer","minimum":0,"description":"Move the step to this 0-based position."},"delay_days":{"type":"integer","minimum":0,"maximum":365,"description":"Wait in whole days. Prefer `delay_minutes`."},"delay_minutes":{"type":"integer","minimum":0,"maximum":525600,"description":"Wait after the previous step's send, in minutes (sends still respect the campaign's schedule window). Takes precedence over `delay_days`."},"subject":{"type":"string","maxLength":998,"description":"May be blank (or omitted) on a follow-up step: the email then goes out in the same thread as `Re: <subject of the previous email>`. The first step needs one."},"body_html":{"type":"string"},"body_text":{"type":"string"},"variants":{"type":["array","null"],"items":{"$ref":"#/components/schemas/SequenceStepVariant"},"maxItems":10,"description":"Replaces the step's variants. Ids are stable: keep an id to edit that variant, drop it to delete the variant (its sends keep their stats). null or [] removes A/B."},"winning_variant_id":{"type":["string","null"]}}},"SequenceStepReorder":{"type":"object","properties":{"step_ids":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":100,"description":"Every step id of the sequence, in the new order. On a campaign, steps active leads have already reached keep their position."}},"required":["step_ids"]},"SequenceStep":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["sequence_step"]},"step_order":{"type":"integer"},"delay_days":{"type":"integer"},"delay_minutes":{"type":"integer","description":"Wait after the previous step, in minutes (authoritative over `delay_days`)."},"subject":{"type":"string","description":"Blank on a follow-up = sent as `Re: <previous subject>` in the same thread."},"body_html":{"type":"string"},"body_text":{"type":"string"},"variants":{"type":["array","null"],"items":{"type":"object","properties":{"id":{"type":"string"},"subject":{"type":"string"},"body_html":{"type":"string"},"body_text":{"type":"string"},"disabled":{"type":"boolean"}},"required":["id","subject","body_html","body_text"]}},"winning_variant_id":{"type":["string","null"]}},"required":["id","object","step_order","delay_days","delay_minutes","subject","body_html","body_text","variants","winning_variant_id"]},"Campaign":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["campaign"]},"mode":{"type":"string","enum":["live","test"]},"name":{"type":"string"},"status":{"type":"string","enum":["draft","running","paused","completed"]},"sequence_id":{"type":["string","null"]},"schedule":{"type":"object","properties":{"timezone":{"type":"string"},"daysOfWeek":{"type":"array","items":{"type":"integer","minimum":1,"maximum":7}},"startHour":{"type":"integer","minimum":0,"maximum":23},"endHour":{"type":"integer","minimum":1,"maximum":24}},"required":["timezone","daysOfWeek","startHour","endHour"]},"sending_inbox_ids":{"type":"array","items":{"type":"string"}},"sending_inbox_tags":{"type":"array","items":{"type":"string"},"description":"Inbox tags the rotation also sends from: every active inbox carrying one of these tags, in addition to `sending_inbox_ids`. Inboxes tagged later join automatically."},"track_opens":{"type":"boolean"},"track_clicks":{"type":"boolean"},"inject_unsubscribe_footer":{"type":"boolean"},"send_status":{"type":["string","null"],"enum":["sending","outside_schedule","no_inbox_available","waiting_on_followup_delays","quota_exceeded","not_entitled","no_active_leads","bounce_protection"],"description":"Read-only. The scheduler's last verdict on why this campaign is or isn't sending: `sending`, `outside_schedule`, `no_inbox_available` (every sender at its cap or throttled), `waiting_on_followup_delays`, `quota_exceeded`, `not_entitled`, `no_active_leads`, or `bounce_protection`. Null until the scheduler has looked at it."},"send_status_at":{"type":["string","null"],"format":"date-time","description":"Read-only. When `send_status` last changed."},"paused_reason":{"type":["string","null"],"description":"Read-only. `bounce_protection` when the system paused the campaign because its hard-bounce rate passed 5% (at least 100 sends); null for a manual pause. Cleared on resume."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"sequence_steps":{"type":"array","items":{"$ref":"#/components/schemas/SequenceStep"}}},"required":["id","object","mode","name","status","sequence_id","schedule","sending_inbox_ids","sending_inbox_tags","track_opens","track_clicks","inject_unsubscribe_footer","send_status","send_status_at","paused_reason","created_at","updated_at"],"example":{"id":"cmp_01HZ8X3J9K7P2QV6R5N4M3T2L7","object":"campaign","mode":"live","name":"Q2 outbound — Tier 1 prospects","status":"running","sequence_id":"seq_01HZ8X3J9K7P2QV6R5N4M3T2L6","schedule":{"timezone":"America/New_York","daysOfWeek":[1,2,3,4,5],"startHour":9,"endHour":17},"sending_inbox_ids":["inb_01HZ8X3J9K7P2QV6R5N4M3T2L1"],"sending_inbox_tags":["outbound"],"track_opens":false,"track_clicks":true,"inject_unsubscribe_footer":true,"send_status":"sending","send_status_at":"2026-05-11T14:22:00Z","paused_reason":null,"created_at":"2026-05-02T16:30:00Z","updated_at":"2026-05-02T16:35:00Z"}},"CampaignList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Campaign"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor","prev_cursor"]},"CampaignCreate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"sequence_id":{"type":"string","pattern":"^seq_"},"sending_inbox_ids":{"type":"array","items":{"type":"string","pattern":"^inb_"},"description":"Explicit sending inboxes. Required unless `sending_inbox_tags` is set."},"sending_inbox_tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Send from every active inbox carrying one of these tags (case-insensitive), in addition to `sending_inbox_ids`."},"schedule":{"type":"object","properties":{"timezone":{"type":"string","minLength":1,"default":"UTC"},"daysOfWeek":{"type":"array","items":{"type":"integer","minimum":1,"maximum":7},"default":[1,2,3,4,5]},"startHour":{"type":"integer","minimum":0,"maximum":23,"default":9},"endHour":{"type":"integer","minimum":1,"maximum":24,"default":17}}},"track_opens":{"type":"boolean","default":false},"track_clicks":{"type":"boolean","default":true},"inject_unsubscribe_footer":{"type":"boolean","default":true}},"required":["name","sequence_id"]},"CampaignPatch":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"sending_inbox_ids":{"type":"array","items":{"type":"string","pattern":"^inb_"},"description":"May be empty when the campaign sends by `sending_inbox_tags`."},"sending_inbox_tags":{"type":["array","null"],"items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Send from every active inbox carrying one of these tags (case-insensitive), in addition to `sending_inbox_ids`."},"schedule":{"type":"object","properties":{"timezone":{"type":"string","minLength":1,"default":"UTC"},"daysOfWeek":{"type":"array","items":{"type":"integer","minimum":1,"maximum":7},"default":[1,2,3,4,5]},"startHour":{"type":"integer","minimum":0,"maximum":23,"default":9},"endHour":{"type":"integer","minimum":1,"maximum":24,"default":17}}},"track_opens":{"type":"boolean"},"track_clicks":{"type":"boolean"},"inject_unsubscribe_footer":{"type":"boolean"}}},"CampaignDryRun":{"type":"object","properties":{"object":{"type":"string","enum":["dry_run"]},"contact_count":{"type":"integer"},"inbox_count":{"type":"integer"},"schedule":{"type":"object","properties":{"timezone":{"type":"string"},"daysOfWeek":{"type":"array","items":{"type":"integer","minimum":1,"maximum":7}},"startHour":{"type":"integer","minimum":0,"maximum":23},"endHour":{"type":"integer","minimum":1,"maximum":24}},"required":["timezone","daysOfWeek","startHour","endHour"]},"first_sends":{"type":"array","items":{"type":"object","properties":{"contact_email":{"type":"string","format":"email"},"inbox_id":{"type":"string"},"scheduled_at":{"type":"string","format":"date-time"}},"required":["contact_email","inbox_id","scheduled_at"]}}},"required":["object","contact_count","inbox_count","schedule","first_sends"]},"CampaignEnrollSkipReasons":{"type":"object","properties":{"unsubscribed":{"type":"integer"},"bounced":{"type":"integer"},"suppressed":{"type":"integer","description":"Blacklisted, or on the workspace suppression list."},"verification":{"type":"integer","description":"Verification result `invalid` or `risky`."},"replied":{"type":"integer","description":"Previously removed from this campaign after replying to it; never re-added."},"in_other_campaign":{"type":"integer","description":"Only with `skip_if_in_other_campaign`."}},"required":["unsubscribed","bounced","suppressed","verification","replied","in_other_campaign"]},"CampaignAttachResult":{"type":"object","properties":{"object":{"type":"string","enum":["attach_result"]},"attached":{"type":"integer","description":"Contacts the campaign gained, including `restored` ones."},"skipped":{"type":"integer","description":"Everything not attached: `already_enrolled` plus every skip reason."},"restored":{"type":"integer","description":"Previously removed from this campaign: back to `active` at the step where they stopped."},"already_enrolled":{"type":"integer"},"not_found":{"type":"integer","description":"Requested contacts that don't exist in this workspace and mode."},"skipped_reasons":{"$ref":"#/components/schemas/CampaignEnrollSkipReasons"}},"required":["object","attached","skipped","restored","already_enrolled","not_found","skipped_reasons"]},"CampaignAttachContacts":{"type":"object","properties":{"contact_ids":{"type":"array","items":{"type":"string","pattern":"^con_"}},"audience_id":{"type":"string","pattern":"^aud_"},"skip_if_in_other_campaign":{"type":"boolean","description":"Skip contacts already enrolled (in any status but `removed`) in another campaign of this workspace."}}},"CampaignContactProgress":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["campaign_contact"]},"contact_id":{"type":"string"},"contact_email":{"type":"string","format":"email"},"current_step":{"type":"integer"},"status":{"type":"string","description":"`active`, `replied`, `bounced`, `unsubscribed`, `finished`, `failed`, or `removed` (taken out of the campaign)."},"next_send_at":{"type":["string","null"],"format":"date-time"},"assigned_inbox_id":{"type":["string","null"]}},"required":["id","object","contact_id","contact_email","current_step","status","next_send_at","assigned_inbox_id"]},"CampaignRemoveResult":{"type":"object","properties":{"object":{"type":"string","enum":["remove_result"]},"removed":{"type":"integer"},"not_active":{"type":"integer","description":"Enrolled but already closed (replied, finished, …) or removed: left alone."},"not_enrolled":{"type":"integer"},"canceled_sends":{"type":"integer"}},"required":["object","removed","not_active","not_enrolled","canceled_sends"]},"CampaignRemoveContacts":{"type":"object","properties":{"contact_ids":{"type":"array","items":{"type":"string","pattern":"^con_"},"minItems":1,"maxItems":1000}},"required":["contact_ids"]},"CampaignMoveResult":{"type":"object","properties":{"object":{"type":"string","enum":["move_result"]},"attached":{"type":"integer","description":"Contacts the campaign gained, including `restored` ones."},"skipped":{"type":"integer","description":"Everything not attached: `already_enrolled` plus every skip reason."},"restored":{"type":"integer","description":"Previously removed from this campaign: back to `active` at the step where they stopped."},"already_enrolled":{"type":"integer"},"not_found":{"type":"integer","description":"Requested contacts that don't exist in this workspace and mode."},"skipped_reasons":{"$ref":"#/components/schemas/CampaignEnrollSkipReasons"},"removed_from_source":{"type":"integer","description":"Active source enrollments set to `removed` because the contact is now in the target. Closed ones (replied, finished, …) stay as history."},"canceled_sends":{"type":"integer"}},"required":["object","attached","skipped","restored","already_enrolled","not_found","skipped_reasons","removed_from_source","canceled_sends"]},"CampaignMoveContacts":{"type":"object","properties":{"to_campaign_id":{"type":"string","pattern":"^cmp_"},"contact_ids":{"type":"array","items":{"type":"string","pattern":"^con_"},"minItems":1,"maxItems":1000},"status":{"type":"string","enum":["active","replied","bounced","unsubscribed","finished","failed"],"description":"Without `contact_ids`: take every enrollment in this status."},"keep_in_source":{"type":"boolean","default":false,"description":"Copy instead of move: the source enrollments stay as they are."},"skip_if_in_other_campaign":{"type":"boolean","description":"Skip contacts enrolled in a campaign other than the source and the target."}},"required":["to_campaign_id"]},"CampaignContactList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/CampaignContactProgress"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor","prev_cursor"]},"CampaignStats":{"type":"object","properties":{"object":{"type":"string","enum":["campaign_stats"]},"sent":{"type":"integer"},"failed":{"type":"integer"},"opened":{"type":"integer"},"clicked":{"type":"integer"},"replied":{"type":"integer"},"bounced":{"type":"integer"},"unsubscribed":{"type":"integer"},"contacts":{"type":"object","properties":{"total":{"type":"integer"},"active":{"type":"integer"},"replied":{"type":"integer"},"bounced":{"type":"integer"},"unsubscribed":{"type":"integer"},"finished":{"type":"integer"},"failed":{"type":"integer"},"removed":{"type":"integer","description":"Taken out of the campaign; not part of `total`."}},"required":["total","active","replied","bounced","unsubscribed","finished","failed","removed"]}},"required":["object","sent","failed","opened","clicked","replied","bounced","unsubscribed","contacts"]},"CampaignPreview":{"type":"object","properties":{"object":{"type":"string","enum":["campaign_preview"]},"campaign_id":{"type":"string"},"contact_id":{"type":["string","null"]},"contact_email":{"type":["string","null"]},"inbox_id":{"type":["string","null"],"description":"The sender rendered as (signature, sender variables)."},"inbox_email":{"type":["string","null"]},"steps":{"type":"array","items":{"type":"object","properties":{"step_id":{"type":"string"},"step_order":{"type":"integer"},"versions":{"type":"array","items":{"type":"object","properties":{"variant_id":{"type":["string","null"],"description":"Null = the step's own content (no A/B variants)."},"label":{"type":"string","description":"`A`, `B`, … as the dashboard names versions."},"disabled":{"type":"boolean"},"picked":{"type":"boolean","description":"The version the scheduler would send this lead."},"subject":{"type":"string"},"body_html":{"type":"string"},"body_text":{"type":"string"}},"required":["variant_id","label","disabled","picked","subject","body_html","body_text"]}}},"required":["step_id","step_order","versions"]}}},"required":["object","campaign_id","contact_id","contact_email","inbox_id","inbox_email","steps"]},"CampaignTestSend":{"type":"object","properties":{"object":{"type":"string","enum":["campaign_test_send"]},"send_id":{"type":"string"},"to":{"type":"string"},"inbox_id":{"type":"string"},"subject":{"type":"string"}},"required":["object","send_id","to","inbox_id","subject"]},"Suppression":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["suppression"]},"mode":{"type":"string","enum":["live","test"]},"email":{"type":"string","format":"email"},"reason":{"type":"string","enum":["unsubscribe","hard_bounce","manual"]},"source_send_id":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"}},"required":["id","object","mode","email","reason","source_send_id","created_at"],"example":{"id":"sup_01HZ8X3J9K7P2QV6R5N4M3T2L8","object":"suppression","mode":"live","email":"alice@example.com","reason":"unsubscribe","source_send_id":"snd_01HZ8X3J9K7P2QV6R5N4M3T2L4","created_at":"2026-04-30T08:14:22Z"}},"SuppressionList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Suppression"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor","prev_cursor"]},"SuppressionCreate":{"type":"object","properties":{"email":{"type":"string","format":"email"},"reason":{"type":"string","enum":["unsubscribe","hard_bounce","manual"],"default":"manual"}},"required":["email"]},"SuppressionBatchResult":{"type":"object","properties":{"object":{"type":"string","enum":["batch_result"]},"created":{"type":"array","items":{"$ref":"#/components/schemas/Suppression"}},"errors":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"email":{"type":"string"},"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["type","code","message"]}},"required":["index","email","error"]}}},"required":["object","created","errors"]},"SuppressionBatch":{"type":"object","properties":{"suppressions":{"type":"array","items":{"$ref":"#/components/schemas/SuppressionCreate"},"minItems":1,"maxItems":1000}},"required":["suppressions"]},"Thread":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["thread"]},"inbox_id":{"type":"string"},"provider_thread_id":{"type":"string","description":"Gmail's resource id."},"subject":{"type":["string","null"]},"message_count":{"type":"integer"},"has_reply":{"type":"boolean"},"has_bounce":{"type":"boolean"},"last_message_at":{"type":["string","null"],"format":"date-time"},"first_message_at":{"type":["string","null"],"format":"date-time"}},"required":["id","object","inbox_id","provider_thread_id","subject","message_count","has_reply","has_bounce","last_message_at","first_message_at"],"example":{"id":"thr_01HZ8X3J9K7P2QV6R5N4M3T2L1_18f8a2b3c4d5e6f","object":"thread","inbox_id":"inb_01HZ8X3J9K7P2QV6R5N4M3T2L1","provider_thread_id":"18f8a2b3c4d5e6f","subject":"Quick question about Acme's data stack","message_count":2,"has_reply":true,"has_bounce":false,"last_message_at":"2026-04-29T16:42:11Z","first_message_at":"2026-04-29T14:30:02Z"}},"ThreadList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Thread"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor","prev_cursor"]},"ThreadReplyCreate":{"type":"object","properties":{"subject":{"type":"string","description":"Defaults to `Re: <last subject in thread>`."},"body_html":{"type":"string"},"body_text":{"type":"string"},"variables":{"type":"object","additionalProperties":{}},"to":{"type":"string","format":"email","description":"Recipient. Optional — defaults to the most recent inbound from_email in the thread."},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"append_signature":{"type":"boolean","description":"Append the inbox's signature to the reply. Default false."}}},"ThreadMessage":{"type":"object","properties":{"id":{"type":"string"},"direction":{"type":"string","enum":["inbound","outbound"]},"classification":{"type":["string","null"],"enum":["reply","auto_reply","bounce","unrelated"]},"from_email":{"type":["string","null"]},"subject":{"type":["string","null"]},"received_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}},"required":["id","direction","classification","from_email","subject","received_at","created_at"]},"ThreadDetail":{"allOf":[{"$ref":"#/components/schemas/Thread"},{"type":"object","properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/ThreadMessage"}}},"required":["messages"]}],"example":{"id":"thr_01HZ8X3J9K7P2QV6R5N4M3T2L1_18f8a2b3c4d5e6f","object":"thread","inbox_id":"inb_01HZ8X3J9K7P2QV6R5N4M3T2L1","provider_thread_id":"18f8a2b3c4d5e6f","subject":"Quick question about Acme's data stack","message_count":2,"has_reply":true,"has_bounce":false,"last_message_at":"2026-04-29T16:42:11Z","first_message_at":"2026-04-29T14:30:02Z"}},"Event":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["event"]},"mode":{"type":"string","enum":["live","test"]},"type":{"type":"string","example":"send.sent"},"resource_id":{"type":"string","description":"Public id of the affected resource."},"data":{"type":"object","additionalProperties":{}},"metadata":{"type":["object","null"],"additionalProperties":{}},"created_at":{"type":"string","format":"date-time"}},"required":["id","object","mode","type","resource_id","data","metadata","created_at"],"example":{"id":"evt_01HZ8X3J9K7P2QV6R5N4M3T2L9","object":"event","mode":"live","type":"message.replied","resource_id":"msg_01HZ8X3J9K7P2QV6R5N4M3T2L5","data":{"message_id":"msg_01HZ8X3J9K7P2QV6R5N4M3T2L5","send_id":"snd_01HZ8X3J9K7P2QV6R5N4M3T2L4","inbox_id":"inb_01HZ8X3J9K7P2QV6R5N4M3T2L1","from_email":"alice@example.com","subject":"Re: Quick question about Acme's data stack"},"metadata":{"mode":"live","crm_record_id":"abc-123"},"created_at":"2026-04-29T16:42:13Z"}},"EventList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor","prev_cursor"]},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string","example":"whk_…"},"object":{"type":"string","enum":["webhook_endpoint"]},"mode":{"type":"string","enum":["live","test"],"description":"Mode of the key that created the endpoint. An endpoint only receives events of its own mode."},"url":{"type":"string","format":"uri"},"description":{"type":["string","null"]},"enabled_events":{"type":"array","items":{"type":"string"},"description":"Subscribed event types. Use `*` to subscribe to all events."},"secret_last_four":{"type":"string"},"disabled_at":{"type":["string","null"],"format":"date-time"},"consecutive_failures":{"type":"integer","description":"Failed attempts since the last successful delivery. The endpoint is disabled after it has been failing for 7 days."},"verified_at":{"type":["string","null"],"format":"date-time","description":"When the endpoint first answered with a 2xx. A new endpoint, or one whose `url` changed, receives a signed `webhook.verification` event and no other events until it acknowledges one."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","object","mode","url","description","enabled_events","secret_last_four","disabled_at","consecutive_failures","verified_at","created_at","updated_at"],"example":{"id":"whk_01HZ8X3J9K7P2QV6R5N4M3T2LA","object":"webhook_endpoint","mode":"live","url":"https://customer.example.com/webhooks/clement","description":"CRM sync — replies, bounces, unsubs","enabled_events":["message.replied","message.bounced","contact.unsubscribed"],"secret_last_four":"f4a2","disabled_at":null,"consecutive_failures":0,"verified_at":"2026-04-26T11:20:01Z","created_at":"2026-04-26T11:20:00Z","updated_at":"2026-04-26T11:20:00Z"}},"WebhookEndpointList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor","prev_cursor"]},"WebhookEndpointWithSecret":{"allOf":[{"$ref":"#/components/schemas/WebhookEndpoint"},{"type":"object","properties":{"secret":{"type":"string","description":"The signing secret. Returned only on create + rotate; never again."}},"required":["secret"]}],"example":{"id":"whk_01HZ8X3J9K7P2QV6R5N4M3T2LA","object":"webhook_endpoint","mode":"live","url":"https://customer.example.com/webhooks/clement","description":"CRM sync — replies, bounces, unsubs","enabled_events":["message.replied","message.bounced","contact.unsubscribed"],"secret_last_four":"f4a2","disabled_at":null,"consecutive_failures":0,"verified_at":"2026-04-26T11:20:01Z","created_at":"2026-04-26T11:20:00Z","updated_at":"2026-04-26T11:20:00Z"}},"WebhookEndpointCreate":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Must be `https://` for live-mode endpoints. Redirects are not followed."},"description":{"type":"string","maxLength":1000},"enabled_events":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Event types to subscribe to (e.g. `[\"message.replied\", \"contact.unsubscribed\"]`). Use `[\"*\"]` for everything."}},"required":["url","enabled_events"]},"WebhookEndpointPatch":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"description":{"type":["string","null"],"maxLength":1000},"enabled_events":{"type":"array","items":{"type":"string","minLength":1},"minItems":1},"disabled":{"type":"boolean","description":"Set to `true` to disable; `false` to re-enable a previously-disabled endpoint."}}},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["webhook_delivery"]},"endpoint_id":{"type":"string"},"event_id":{"type":["string","null"]},"attempt":{"type":"integer"},"outcome":{"type":"string","enum":["pending","succeeded","failed"]},"status_code":{"type":["integer","null"]},"latency_ms":{"type":["integer","null"]},"error":{"type":["string","null"]},"delivered_at":{"type":["string","null"],"format":"date-time"},"next_retry_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}},"required":["id","object","endpoint_id","event_id","attempt","outcome","status_code","latency_ms","error","delivered_at","next_retry_at","created_at"],"example":{"id":"whd_01HZ8X3J9K7P2QV6R5N4M3T2LB","object":"webhook_delivery","endpoint_id":"whk_01HZ8X3J9K7P2QV6R5N4M3T2LA","event_id":"evt_01HZ8X3J9K7P2QV6R5N4M3T2L9","attempt":1,"outcome":"succeeded","status_code":200,"latency_ms":124,"error":null,"delivered_at":"2026-04-29T16:42:14Z","next_retry_at":null,"created_at":"2026-04-29T16:42:14Z"}},"WebhookDeliveryList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor","prev_cursor"]},"WorkspaceLimits":{"type":["object","null"],"properties":{"contacts":{"type":["integer","null"],"description":"null = unlimited"},"sends_per_month":{"type":["integer","null"],"description":"null = unlimited"},"webhooks":{"type":["integer","null"],"description":"null = unlimited"},"inboxes":{"type":["integer","null"],"description":"null = unlimited"}},"required":["contacts","sends_per_month","webhooks","inboxes"],"description":"Plan caps. null when no active subscription."},"WorkspaceUsage":{"type":"object","properties":{"contacts":{"type":"integer"},"sends_this_month":{"type":"integer","description":"Live sends created this calendar month (UTC) that are queued, sending, sent or failed. Sends canceled before pickup don't count."},"webhooks":{"type":"integer"},"inboxes":{"type":"integer"}},"required":["contacts","sends_this_month","webhooks","inboxes"]},"Workspace":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["workspace"]},"name":{"type":"string"},"slug":{"type":["string","null"]},"plan":{"type":["string","null"],"enum":["pro","scale","hyper"],"description":"Active subscription tier. null when no entitling subscription is in effect."},"plan_status":{"type":["string","null"],"enum":["trialing","active","past_due"],"description":"Status of the active subscription, mirroring Stripe values."},"trial_ends_at":{"type":["string","null"],"format":"date-time"},"current_period_end":{"type":["string","null"],"format":"date-time"},"cancel_at_period_end":{"type":"boolean"},"limits":{"$ref":"#/components/schemas/WorkspaceLimits"},"usage":{"$ref":"#/components/schemas/WorkspaceUsage"},"created_at":{"type":"string","format":"date-time"}},"required":["id","object","name","slug","plan","plan_status","trial_ends_at","current_period_end","cancel_at_period_end","limits","usage","created_at"],"example":{"id":"wsp_01HZ8X3J9K7P2QV6R5N4M3T2LD","object":"workspace","name":"Acme","slug":"acme","plan":"scale","plan_status":"active","trial_ends_at":null,"current_period_end":"2026-05-15T00:00:00Z","cancel_at_period_end":false,"limits":{"contacts":30000,"sends_per_month":100000,"webhooks":20,"inboxes":null},"usage":{"contacts":4218,"sends_this_month":12483,"webhooks":3,"inboxes":7},"created_at":"2026-03-01T08:00:00Z"}}},"parameters":{}},"paths":{"/v1/health":{"get":{"summary":"Liveness probe","description":"Cheap liveness probe. Returns 200 if the API process is up. Does not check downstream dependencies (database, redis) — that's `/v1/health/ready`.","tags":["meta"],"responses":{"200":{"description":"Service is alive","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/v1/api_keys":{"get":{"summary":"List API keys in the workspace","description":"Lists keys of the calling key's mode (a `cl_test_*` key sees only test keys). Dashboard sessions see both modes.","tags":["api_keys"],"security":[{"bearer":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"post":{"summary":"Create an API key (secret returned once)","description":"An API key can only create keys of its own mode: a `cl_test_*` admin key can't mint `cl_live_*` keys (403). Dashboard sessions can create either.","tags":["api_keys"],"security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreate"}}}},"responses":{"201":{"description":"Created — `secret` is in the response and never returned again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyWithSecret"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/api_keys/{id}/rotate":{"post":{"summary":"Rotate an API key (issues a new secret, revokes the old one)","description":"Confirmation guard: `?confirm=true` required (or a calling key with `auto_confirm: true`). Without it returns 400 with `code: confirmation_required` — rotation invalidates the old secret immediately and any caller still using it will start getting 401s. API keys can only rotate keys of their own mode; others return 404.","tags":["api_keys"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^key_"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["true"],"description":"Required unless the calling key has `auto_confirm: true`."},"required":false,"name":"confirm","in":"query"}],"responses":{"200":{"description":"Rotated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyWithSecret"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/api_keys/{id}":{"delete":{"summary":"Revoke an API key","description":"API keys can only revoke keys of their own mode; others return 404. Dashboard sessions can revoke either.","tags":["api_keys"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^key_"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["true"],"description":"Required unless the calling key has `auto_confirm: true`."},"required":false,"name":"confirm","in":"query"}],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKey"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/inboxes":{"get":{"summary":"List inboxes in the workspace","tags":["inboxes"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ending_before","in":"query"},{"schema":{"type":"string","description":"Filter by provider (e.g. `gmail`)."},"required":false,"name":"provider","in":"query"},{"schema":{"type":"string","enum":["connecting","active","token_expired","revoked","over_quota_today","unhealthy","paused","failed"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","description":"Only inboxes carrying this tag (case-insensitive)."},"required":false,"name":"tag","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/inboxes/{id}":{"get":{"summary":"Retrieve an inbox","tags":["inboxes"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^inb_[0-9A-Za-z]{26}$","example":"inb_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Inbox"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"patch":{"summary":"Update an inbox's settings","description":"Sender name, daily limit and ramp-up, signature, reply-to, timezone and tags for any inbox; `warmup_enabled` for Gmail inboxes; `sandbox_config` for sandbox inboxes. Requires a write-scoped key.","tags":["inboxes"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^inb_[0-9A-Za-z]{26}$","example":"inb_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxSandboxPatch"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Inbox"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"delete":{"summary":"Delete an inbox (sandbox only via API)","description":"Hard-delete for sandbox inboxes. Real-provider (Gmail) disconnect still goes through the dashboard. `?confirm=true` required (high-blast-radius).","tags":["inboxes"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^inb_[0-9A-Za-z]{26}$","example":"inb_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["true"]},"required":false,"name":"confirm","in":"query"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Inbox"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/inboxes/google/connect_link":{"post":{"summary":"Mint a one-time Gmail OAuth connect URL","description":"Returns a URL the customer/agent visits in a browser to OAuth-connect a Gmail inbox to this workspace. OAuth requires a browser session; the API layer cannot drive it directly. Agents typically DM the URL to a human, who clicks it and grants Google permissions. After consent, the inbox lands attached to the same workspace this key belongs to.","tags":["inboxes"],"security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxGoogleConnectLinkCreate"}}}},"responses":{"201":{"description":"Connect URL minted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxGoogleConnectLink"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/inboxes/smtp":{"post":{"summary":"Connect an SMTP/IMAP inbox","description":"Connects a mailbox by credentials: SMTP for sending, IMAP for reply and bounce detection. Clement logs in to both servers before saving; if either login fails the call returns `422 inbox_connection_failed` and nothing is stored. Re-posting an already-connected SMTP address updates its credentials and reactivates it (200). Live mode only. Passwords are encrypted at rest and never returned. Port 25 is not supported.","tags":["inboxes"],"security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxSmtpCreate"}}}},"responses":{"200":{"description":"Existing SMTP inbox reconnected with new credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Inbox"}}}},"201":{"description":"Connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Inbox"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/inboxes/sandbox":{"post":{"summary":"Create a sandbox inbox (test mode only)","description":"Sandbox inboxes do not connect to a real provider. Sends targeting them transition straight to `sent` and the worker generates synthetic open / click / reply / bounce events on the configured schedule. Available only with a `cl_test_*` key — see API-PLAN §11.","tags":["inboxes"],"security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxSandboxCreate"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Inbox"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/sends":{"post":{"summary":"Send an email (single or fan-out across inboxes)","description":"**The send primitive** (API-PLAN §6). Single recipient → returns the `Send`. Multi-recipient or `from_strategy` → returns a `BulkSendResult` with per-recipient outcomes.","tags":["sends"],"security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendCreate"}}}},"responses":{"201":{"description":"Send(s) scheduled","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/Send"},{"$ref":"#/components/schemas/BulkSendResult"}]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"get":{"summary":"List sends","tags":["sends"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ending_before","in":"query"},{"schema":{"type":"string"},"required":false,"name":"inbox_id","in":"query"},{"schema":{"type":"string","enum":["scheduled","sending","sent","failed"]},"required":false,"name":"state","in":"query"},{"schema":{"type":"string","description":"Comma-separated. Allowed values: inbox.","example":"inbox"},"required":false,"name":"expand","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/sends/{id}/cancel":{"post":{"summary":"Cancel a scheduled send","description":"Only valid while the send is in state `scheduled`. Returns 409 once the worker has picked the job up (`sending` or beyond — the email may already be on its way to Gmail).","tags":["sends"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^snd_[0-9A-Za-z]{26}$","example":"snd_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Canceled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Send"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/sends/{id}":{"get":{"summary":"Retrieve a send","tags":["sends"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^snd_[0-9A-Za-z]{26}$","example":"snd_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Comma-separated. Allowed values: inbox.","example":"inbox"},"required":false,"name":"expand","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Send"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/messages":{"get":{"summary":"List messages","tags":["messages"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ending_before","in":"query"},{"schema":{"type":"string"},"required":false,"name":"inbox_id","in":"query"},{"schema":{"type":"string","enum":["inbound","outbound"]},"required":false,"name":"direction","in":"query"},{"schema":{"type":"string","enum":["reply","auto_reply","bounce","unrelated"]},"required":false,"name":"classification","in":"query"},{"schema":{"type":"string"},"required":false,"name":"thread_id","in":"query"},{"schema":{"type":"string","description":"Comma-separated. Allowed values: inbox.","example":"inbox"},"required":false,"name":"expand","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/messages/{id}":{"get":{"summary":"Retrieve a message","tags":["messages"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^msg_[0-9A-Za-z]{26}$","example":"msg_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Comma-separated. Allowed values: inbox.","example":"inbox"},"required":false,"name":"expand","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/messages/{id}/body":{"get":{"summary":"Retrieve a message's body","description":"Fetches the body from the mailbox on demand (Gmail API or IMAP); Clement stores headers only. Slower than other reads and counts against the inbox provider's rate limits, so fetch the messages you need. 502 `body_unavailable` when the provider can't return it (inbox disconnected, message deleted, token expired). Sandbox inboxes have no stored body (`html` and `text` null).","tags":["messages"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^msg_[0-9A-Za-z]{26}$","example":"msg_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageBody"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/contacts":{"get":{"summary":"List contacts","tags":["contacts"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ending_before","in":"query"},{"schema":{"type":"string","format":"email"},"required":false,"name":"email","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Case-insensitive substring match on the email address."},"required":false,"name":"q","in":"query"},{"schema":{"type":"string","enum":["ok","unsubscribed","bounced","blacklisted"]},"required":false,"name":"global_status","in":"query"},{"schema":{"type":"string","enum":["interested","meeting_booked","not_interested"]},"required":false,"name":"lead_status","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"post":{"summary":"Create a contact (idempotent on email)","description":"Returns the existing contact (HTTP 200) when the email is already in this workspace. Otherwise creates and returns the new contact (HTTP 201).","tags":["contacts"],"security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactCreate"}}}},"responses":{"200":{"description":"Existing contact returned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contact"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contact"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/contacts/{id}":{"get":{"summary":"Retrieve a contact","tags":["contacts"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^con_[0-9A-Za-z]{26}$","example":"con_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contact"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"patch":{"summary":"Update a contact","tags":["contacts"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^con_[0-9A-Za-z]{26}$","example":"con_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactPatch"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contact"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"delete":{"summary":"Delete a contact","description":"Hard delete. Cascades to `campaign_contacts`; historical `sends` keep their email snapshot.","tags":["contacts"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^con_[0-9A-Za-z]{26}$","example":"con_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contact"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/contacts/batch":{"post":{"summary":"Create up to 1,000 contacts in one call","description":"Per-row idempotency on email — existing contacts are returned alongside newly-created ones. Validation failures are reported per-row in `errors`; partial success is the norm.","tags":["contacts"],"security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactBatch"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactBatchResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/contacts/{id}/lead_status":{"post":{"summary":"Set a contact's lead status","description":"Tags the lead `interested`, `meeting_booked` or `not_interested`, as the dashboard's inbox does after a reply. `not_interested` also stops the sequence: the contact's active or replied enrollments (only the one in `campaign_id` when given) become `unsubscribed`. Emits `contact.lead_status_changed` when the status changes.","tags":["contacts"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^con_[0-9A-Za-z]{26}$","example":"con_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"lead_status":{"type":"string","enum":["interested","meeting_booked","not_interested"]},"campaign_id":{"type":"string","pattern":"^cmp_","description":"The campaign the reply came from: limits `not_interested` to that enrollment and is recorded on the event."}},"required":["lead_status"]}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contact"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/contact_imports":{"get":{"summary":"List contact import jobs","tags":["contacts","imports"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ending_before","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"post":{"summary":"Bulk-import contacts from a CSV","description":"v1 processes synchronously; the response is the completed (or failed) import job. Larger files (>50k rows) will move to async polling once worker support lands; the resource shape is forward-compatible with `status: queued`.\n\n`?dry_run=true` parses + validates the CSV without writing any contacts, audience rows, or import_jobs row. Useful for agents that want to surface row-level errors to a human before committing.","tags":["contacts","imports"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","enum":["true"],"description":"When `true`, returns the parse + validation report without persisting anything. The response carries `object: \"contact_import_dry_run\"` and a synthetic `dryrun_…` id; quota is not consumed."},"required":false,"name":"dry_run","in":"query"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/ContactImportCreate"}}}},"responses":{"200":{"description":"Dry-run result (only when `?dry_run=true`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportDryRun"}}}},"201":{"description":"Import created (and processed in this request)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImport"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/contact_imports/{id}":{"get":{"summary":"Retrieve a contact import job","tags":["contacts","imports"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^imp_[0-9A-Za-z]{26}$","example":"imp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImport"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/audiences":{"get":{"summary":"List audiences","tags":["audiences"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ending_before","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"post":{"summary":"Create an audience","tags":["audiences"],"security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceCreate"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Audience"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/audiences/{id}":{"get":{"summary":"Retrieve an audience","tags":["audiences"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^aud_[0-9A-Za-z]{26}$","example":"aud_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Audience"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"patch":{"summary":"Update an audience","tags":["audiences"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^aud_[0-9A-Za-z]{26}$","example":"aud_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudiencePatch"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Audience"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"delete":{"summary":"Delete an audience","description":"Cascades to `audience_contacts`; underlying contacts are unaffected. `?confirm=true` is required when the audience contains any contacts.","tags":["audiences"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^aud_[0-9A-Za-z]{26}$","example":"aud_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["true"]},"required":false,"name":"confirm","in":"query"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Audience"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/audiences/{id}/contacts":{"post":{"summary":"Attach contacts to an audience","description":"Idempotent on `(audience, contact)`. Up to 1,000 contact IDs per call.","tags":["audiences"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^aud_[0-9A-Za-z]{26}$","example":"aud_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceAttachContacts"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceAttachResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/audiences/{id}/contacts/{contact_id}":{"delete":{"summary":"Detach one contact from an audience","tags":["audiences"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^aud_[0-9A-Za-z]{26}$","example":"aud_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^con_[0-9A-Za-z]{26}$","example":"con_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"contact_id","in":"path"}],"responses":{"204":{"description":"Detached"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/sequences":{"get":{"summary":"List sequences","tags":["sequences"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ending_before","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"post":{"summary":"Create a sequence (optionally with initial steps)","tags":["sequences"],"security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceCreate"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sequence"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/sequences/{id}":{"get":{"summary":"Retrieve a sequence (with steps embedded)","tags":["sequences"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^seq_[0-9A-Za-z]{26}$","example":"seq_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sequence"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"patch":{"summary":"Update sequence metadata","tags":["sequences"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^seq_[0-9A-Za-z]{26}$","example":"seq_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequencePatch"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sequence"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"delete":{"summary":"Delete a sequence","description":"Cascades to template steps. Campaigns launched from the sequence keep their own copy of the steps.","tags":["sequences"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^seq_[0-9A-Za-z]{26}$","example":"seq_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sequence"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/sequences/{id}/steps":{"post":{"summary":"Add a step to a sequence","description":"Appends, or inserts at `step_order` and shifts the later steps down. A follow-up step may leave `subject` blank to reply in the same thread.","tags":["sequences"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^seq_[0-9A-Za-z]{26}$","example":"seq_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"step_order":{"type":"integer","minimum":0,"description":"0-based position. Omit to append; an existing position inserts before that step."},"delay_days":{"type":"integer","minimum":0,"maximum":365,"description":"Wait in whole days. Prefer `delay_minutes`."},"delay_minutes":{"type":"integer","minimum":0,"maximum":525600,"description":"Wait after the previous step's send, in minutes (sends still respect the campaign's schedule window). Takes precedence over `delay_days`."},"subject":{"type":"string","maxLength":998,"description":"May be blank (or omitted) on a follow-up step: the email then goes out in the same thread as `Re: <subject of the previous email>`. The first step needs one."},"body_html":{"type":"string"},"body_text":{"type":"string"},"variants":{"type":"array","items":{"$ref":"#/components/schemas/SequenceStepVariant"},"maxItems":10},"winning_variant_id":{"type":"string"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceStepStandalone"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/sequences/{id}/steps/{step_id}":{"patch":{"summary":"Update a step","description":"Edit content, delay or variants, or move the step with `step_order` (the other steps shift). Only template steps are edited; campaigns keep their own copy (edit those via /v1/campaigns/{id}/steps).","tags":["sequences"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^seq_[0-9A-Za-z]{26}$","example":"seq_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^seq_[0-9A-Za-z]{26}$","example":"seq_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"step_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceStepPatch"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceStepStandalone"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"delete":{"summary":"Delete a step","description":"The later steps shift up to close the gap.","tags":["sequences"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^seq_[0-9A-Za-z]{26}$","example":"seq_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^seq_[0-9A-Za-z]{26}$","example":"seq_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"step_id","in":"path"}],"responses":{"204":{"description":"Deleted"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/sequences/{id}/steps/reorder":{"post":{"summary":"Reorder a sequence's steps","tags":["sequences"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^seq_[0-9A-Za-z]{26}$","example":"seq_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceStepReorder"}}}},"responses":{"200":{"description":"Reordered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sequence"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns":{"get":{"summary":"List campaigns","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ending_before","in":"query"},{"schema":{"type":"string","enum":["draft","running","paused","completed"]},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"post":{"summary":"Create a campaign (snapshots the source sequence's steps)","description":"Copies the steps of `sequence_id` into per-campaign rows so future edits to the sequence template don't affect this campaign. The new campaign starts in state `draft`; call POST /v1/campaigns/{id}/start to launch.","tags":["campaigns"],"security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignCreate"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}":{"get":{"summary":"Retrieve a campaign (with sequence steps embedded)","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"patch":{"summary":"Update a campaign","description":"Mutable while in `draft` or `paused`; mutating a `running` campaign is rejected with 409 — pause first.","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignPatch"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"delete":{"summary":"Delete a campaign","description":"Cascades to its snapshot sequence_steps and campaign_contacts. Queued (not yet sent) sends of its contacts are canceled; sends already handed to the provider complete. Historical sends keep their email snapshot. Confirmation required when status is `running`.","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["true"]},"required":false,"name":"confirm","in":"query"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}/start":{"post":{"summary":"Start a campaign (or preview with ?dry_run=true)","description":"Transitions `draft` or `paused` → `running`. Refused with 409 `campaign_not_ready` (every problem listed) when the campaign has no steps, the first step has no subject or body, no active sending inbox resolves from `sending_inbox_ids` / `sending_inbox_tags`, or no contact is active. Pass `?dry_run=true` to return the projected schedule (which inboxes, when, to whom — first 10 sends) without committing.","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["true"]},"required":false,"name":"dry_run","in":"query"}],"responses":{"200":{"description":"Running (or projected schedule under dry_run)","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/Campaign"},{"$ref":"#/components/schemas/CampaignDryRun"}]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}/pause":{"post":{"summary":"Pause a running campaign","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Paused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}/resume":{"post":{"summary":"Resume a paused campaign","description":"Same preflight as start (409 `campaign_not_ready`). Resuming after a bounce-protection pause gives the campaign 24 hours and 50 sends before the bounce check looks again, counting only sends since the resume.","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Resumed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}/contacts":{"post":{"summary":"Attach contacts (or an audience) to a campaign","description":"Idempotent on `(campaign, contact)`. Pass either `contact_ids` (up to 1,000) or `audience_id` (all contacts in the audience, snapshotted now). Unsubscribed, bounced, suppressed and `invalid`/`risky`-verified contacts are skipped and counted by reason. A contact previously removed from this campaign resumes where it stopped, unless it replied. Attaching new contacts to a `completed` campaign puts it back to `running` (emits `campaign.resumed`).","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignAttachContacts"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignAttachResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"get":{"summary":"List contacts attached to this campaign with progress","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ending_before","in":"query"},{"schema":{"type":"string","enum":["active","replied","bounced","unsubscribed","finished","failed","removed"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","maxLength":320,"description":"Case-insensitive substring match on the contact's email."},"required":false,"name":"email","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignContactList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}/contacts/{contact_id}":{"delete":{"summary":"Remove a contact from a campaign","description":"Sets an `active` enrollment to `removed` and cancels its queued (`scheduled`) send. A send already being handed to the provider (`sending`) can't be recalled. The enrollment and its sends stay for history; removed leads don't count as replied or finished. Idempotent for an already-removed contact; 409 `enrollment_not_active` when the lead already replied, finished, bounced, unsubscribed or failed.","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^con_[0-9A-Za-z]{26}$","example":"con_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"contact_id","in":"path"}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignContactProgress"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}/contacts/remove":{"post":{"summary":"Remove contacts from a campaign (bulk)","description":"Bulk form of `DELETE /v1/campaigns/{id}/contacts/{contact_id}`, up to 1,000 ids.","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignRemoveContacts"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignRemoveResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}/contacts/move":{"post":{"summary":"Move or copy contacts to another campaign","description":"Enrolls the contacts in `to_campaign_id` under that campaign's rules (fresh start at step 0; same skip reasons as attaching), then removes them from this campaign — only those now in the target, so a skipped contact stays where it was. `keep_in_source: true` copies instead.","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignMoveContacts"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignMoveResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}/stats":{"get":{"summary":"Campaign aggregate stats","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignStats"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}/steps":{"post":{"summary":"Add a step to a campaign","description":"Appends, or inserts at `step_order` (only after the steps leads have already reached). Finished leads don't receive a newly appended step, and a completed campaign stays completed.","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"step_order":{"type":"integer","minimum":0,"description":"0-based position. Omit to append; an existing position inserts before that step."},"delay_days":{"type":"integer","minimum":0,"maximum":365,"description":"Wait in whole days. Prefer `delay_minutes`."},"delay_minutes":{"type":"integer","minimum":0,"maximum":525600,"description":"Wait after the previous step's send, in minutes (sends still respect the campaign's schedule window). Takes precedence over `delay_days`."},"subject":{"type":"string","maxLength":998,"description":"May be blank (or omitted) on a follow-up step: the email then goes out in the same thread as `Re: <subject of the previous email>`. The first step needs one."},"body_html":{"type":"string"},"body_text":{"type":"string"},"variants":{"type":"array","items":{"$ref":"#/components/schemas/SequenceStepVariant"},"maxItems":10},"winning_variant_id":{"type":"string"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceStep"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}/steps/{step_id}":{"patch":{"summary":"Update a campaign step","description":"Allowed while the campaign runs. Content, delay and variant edits apply to emails rendered after the change; already queued sends keep their content and leads already waiting keep their computed send time. Moving the step (`step_order`) follows the reorder rules.","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^seq_[0-9A-Za-z]{26}$","example":"seq_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"step_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"step_order":{"type":"integer","minimum":0,"description":"Move the step to this 0-based position."},"delay_days":{"type":"integer","minimum":0,"maximum":365,"description":"Wait in whole days. Prefer `delay_minutes`."},"delay_minutes":{"type":"integer","minimum":0,"maximum":525600,"description":"Wait after the previous step's send, in minutes (sends still respect the campaign's schedule window). Takes precedence over `delay_days`."},"subject":{"type":"string","maxLength":998,"description":"May be blank (or omitted) on a follow-up step: the email then goes out in the same thread as `Re: <subject of the previous email>`. The first step needs one."},"body_html":{"type":"string"},"body_text":{"type":"string"},"variants":{"type":["array","null"],"items":{"$ref":"#/components/schemas/SequenceStepVariant"},"maxItems":10,"description":"Replaces the step's variants. Ids are stable: keep an id to edit that variant, drop it to delete the variant (its sends keep their stats). null or [] removes A/B."},"winning_variant_id":{"type":["string","null"]}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceStep"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"delete":{"summary":"Delete a campaign step","description":"Refused with 409 once active leads have reached the step. Sends of the step keep their content and stats.","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^seq_[0-9A-Za-z]{26}$","example":"seq_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"step_id","in":"path"}],"responses":{"204":{"description":"Deleted"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}/steps/reorder":{"post":{"summary":"Reorder a campaign's steps","description":"Pass every step id in the new order. Steps active leads have already reached must keep their position (409 otherwise).","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceStepReorder"}}}},"responses":{"200":{"description":"Reordered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}/duplicate":{"post":{"summary":"Duplicate a campaign","description":"Creates a `draft` copy with the same settings, schedule, sending inboxes/tags and steps (variants included, picked winners cleared). Leads are not copied; enroll them with POST /v1/campaigns/{id}/contacts. The copy is named `<name> (copy)` unless `name` is given.","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}/preview":{"get":{"summary":"Preview a campaign's emails for a lead","description":"Renders every version of every step exactly as the scheduler would for one lead: variables and fallbacks, spintax, the sender's signature, and `Re: <previous subject>` for blank follow-up subjects. `contact_id` must be enrolled in the campaign; without it, variables render empty. The sender is `inbox_id`, else the lead's assigned inbox, else the first active sending inbox.","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^con_"},"required":false,"name":"contact_id","in":"query"},{"schema":{"type":"string","pattern":"^inb_"},"required":false,"name":"inbox_id","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignPreview"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/campaigns/{id}/test_send":{"post":{"summary":"Send a test email of one campaign step","description":"Sends one rendered step (optionally one variant, rendered for `contact_id`) from one of the campaign's sending inboxes to a member of the workspace. Live campaigns only. It's an ad-hoc send: it never moves a lead or shows in campaign stats, but counts against the monthly sends quota. 20 per member per hour, shared with the dashboard.","tags":["campaigns"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9A-Za-z]{26}$","example":"cmp_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"step_id":{"type":"string","pattern":"^seq_"},"variant_id":{"type":"string","description":"Required when the step has variants (ids from the step's `variants`)."},"to":{"type":"string","format":"email","description":"A workspace member's email address."},"inbox_id":{"type":"string","pattern":"^inb_","description":"Defaults to the first active sending inbox."},"contact_id":{"type":"string","pattern":"^con_","description":"Render with this enrolled lead's variables."}},"required":["step_id","to"]}}}},"responses":{"201":{"description":"Queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignTestSend"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/suppressions":{"get":{"summary":"List suppressions","tags":["suppressions"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ending_before","in":"query"},{"schema":{"type":"string","format":"email"},"required":false,"name":"email","in":"query"},{"schema":{"type":"string","enum":["unsubscribe","hard_bounce","manual"]},"required":false,"name":"reason","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"post":{"summary":"Add an email to the suppression list","description":"Idempotent on email — re-POSTing the same email returns the existing row (200) rather than 201.","tags":["suppressions"],"security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionCreate"}}}},"responses":{"200":{"description":"Existing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Suppression"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Suppression"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/suppressions/{id}":{"get":{"summary":"Retrieve a suppression","tags":["suppressions"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^sup_[0-9A-Za-z]{26}$","example":"sup_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Suppression"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"delete":{"summary":"Remove a suppression","description":"Admin-scope required (recipient comes off the global block list and may receive future sends).","tags":["suppressions"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^sup_[0-9A-Za-z]{26}$","example":"sup_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Suppression"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/suppressions/batch":{"post":{"summary":"Add up to 1,000 suppressions in one call","tags":["suppressions"],"security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionBatch"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionBatchResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/threads":{"get":{"summary":"List threads","tags":["threads"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ending_before","in":"query"},{"schema":{"type":"string"},"required":false,"name":"inbox_id","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Filter to threads where any inbound message was classified `reply`."},"required":false,"name":"has_reply","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreadList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/threads/{id}/replies":{"post":{"summary":"Reply in a thread (sugar over POST /v1/sends)","description":"Routes through the same send pipeline as POST /v1/sends, but pre-fills `thread_id_to` and `in_reply_to_message_id` from the thread, and defaults the recipient + subject when omitted.","tags":["threads","sends"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^thr_[0-9A-Za-z]{26}_.+$"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreadReplyCreate"}}}},"responses":{"201":{"description":"Reply scheduled","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/threads/{id}":{"get":{"summary":"Retrieve a thread (with messages embedded)","tags":["threads"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^thr_[0-9A-Za-z]{26}_.+$"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreadDetail"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/events":{"get":{"summary":"List events","tags":["events"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ending_before","in":"query"},{"schema":{"type":"string","description":"Filter by event type, e.g. `send.sent`."},"required":false,"name":"type","in":"query"},{"schema":{"type":"string","description":"Filter to events about this resource (public id)."},"required":false,"name":"resource_id","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/events/{id}":{"get":{"summary":"Retrieve an event","tags":["events"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^evt_[0-9A-Za-z]{26}$","example":"evt_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/webhooks":{"get":{"summary":"List webhook endpoints","tags":["webhooks"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ending_before","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"post":{"summary":"Create a webhook endpoint (signing secret returned once)","description":"The endpoint takes the calling key's mode and receives only events of that mode: create it with a `cl_test_*` key to receive test-mode events. Live endpoints must use `https://` and a public host. Clement immediately sends the endpoint a signed `webhook.verification` event; once it answers with any 2xx, `verified_at` is set and events start flowing. Until then it receives no other events (verification retries on the normal schedule, and a successful `/test` delivery also verifies it).","tags":["webhooks"],"security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreate"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointWithSecret"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/webhooks/{id}":{"get":{"summary":"Retrieve a webhook endpoint","tags":["webhooks"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^whk_[0-9A-Za-z]{26}$","example":"whk_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"patch":{"summary":"Update a webhook endpoint","tags":["webhooks"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^whk_[0-9A-Za-z]{26}$","example":"whk_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointPatch"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"delete":{"summary":"Delete a webhook endpoint","tags":["webhooks"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^whk_[0-9A-Za-z]{26}$","example":"whk_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/webhooks/{id}/rotate":{"post":{"summary":"Rotate the signing secret","description":"Issues a new `whsec_…` secret. The old one stops working immediately. Update your verifier to the new secret as soon as the rotate response lands.","tags":["webhooks"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^whk_[0-9A-Za-z]{26}$","example":"whk_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Rotated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointWithSecret"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/webhooks/{id}/test":{"post":{"summary":"Send a synthetic test delivery to this endpoint","description":"Delivers a `webhook.test` event with `metadata.test = true` so the customer's endpoint can verify wiring without depending on real product activity.","tags":["webhooks"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^whk_[0-9A-Za-z]{26}$","example":"whk_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"}],"responses":{"202":{"description":"Test queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/webhooks/{id}/deliveries":{"get":{"summary":"List delivery attempts for this endpoint","tags":["webhooks"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^whk_[0-9A-Za-z]{26}$","example":"whk_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ending_before","in":"query"},{"schema":{"type":"string","enum":["pending","succeeded","failed"]},"required":false,"name":"outcome","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/webhooks/{id}/deliveries/{delivery_id}":{"get":{"summary":"Retrieve a single delivery attempt","tags":["webhooks"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^whk_[0-9A-Za-z]{26}$","example":"whk_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^whk_[0-9A-Za-z]{26}$","example":"whk_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"delivery_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/webhooks/{id}/deliveries/{delivery_id}/redeliver":{"post":{"summary":"Replay a delivery (creates a new attempt with the same payload)","tags":["webhooks"],"security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","pattern":"^whk_[0-9A-Za-z]{26}$","example":"whk_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^whk_[0-9A-Za-z]{26}$","example":"whk_AM788072KD0X99RP8HK5AH0000"},"required":true,"name":"delivery_id","in":"path"}],"responses":{"202":{"description":"Redelivery queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/workspace":{"get":{"summary":"Retrieve the workspace bound to this key","description":"Returns the workspace's plan, limits, and current usage. Useful for agents bootstrapping context — `usage` against `limits` tells you how much headroom is left before quota.","tags":["workspace"],"security":[{"bearer":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Workspace"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}}},"webhooks":{}}