{"openapi":"3.1.0","info":{"title":"Missivia — e-mail routing API","version":"1.1.5","description":"Headless multi-tenant API for routing e-mail series. The tenant is derived from the API key (Bearer). Errors follow RFC 9457."},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"API key `rt_live_…` / `rt_test_…` / `rt_admin_…`"}},"schemas":{"ScoringRulesInput":{"type":"object","properties":{"weights":{"type":"object","properties":{"opened":{"type":"integer","minimum":-100,"maximum":100},"clicked":{"type":"integer","minimum":-100,"maximum":100},"delivered":{"type":"integer","minimum":-100,"maximum":100},"bounced_soft":{"type":"integer","minimum":-100,"maximum":100},"unsubscribed":{"type":"integer","minimum":-100,"maximum":100},"complained":{"type":"integer","minimum":-100,"maximum":100},"list.subscribed":{"type":"integer","minimum":-100,"maximum":100},"consent.granted":{"type":"integer","minimum":-100,"maximum":100}},"description":"Points granted per event type (integers between -100 and 100)"},"decay_per_day":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Points removed per full day without a score update"},"min":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"max":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["weights","decay_per_day","min","max"]},"SegmentAttributeRuleInput":{"type":"object","properties":{"kind":{"type":"string","const":"attribute"},"field":{"type":"string","minLength":1,"maxLength":100},"operator":{"type":"string","enum":["eq","neq","contains","not_contains","starts_with","gt","gte","lt","lte","between","in","not_in","exists","not_exists","before","after","within_last_days","older_than_days"]},"value":{"anyOf":[{"type":["string","number","boolean"]},{"type":"array","items":{"type":["string","number","boolean"]}}]}},"required":["kind","field","operator"]},"SegmentStatusRuleInput":{"type":"object","properties":{"kind":{"type":"string","const":"status"},"operator":{"type":"string","enum":["eq","neq","in"]},"value":{"anyOf":[{"type":"string","enum":["active","unsubscribed","bounced","complained","suppressed"]},{"type":"array","items":{"type":"string","enum":["active","unsubscribed","bounced","complained","suppressed"]}}]}},"required":["kind","operator","value"]},"SegmentListRuleInput":{"type":"object","properties":{"kind":{"type":"string","const":"list"},"list_id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$"},"operator":{"type":"string","enum":["in","not_in"]}},"required":["kind","list_id","operator"]},"SegmentEventRuleInput":{"type":"object","properties":{"kind":{"type":"string","const":"event"},"event_type":{"type":"string","enum":["sent","delivered","opened","clicked","bounced","complained","unsubscribed"]},"operator":{"type":"string","enum":["occurred","not_occurred"]},"within_days":{"type":"integer","minimum":1,"maximum":3650}},"required":["kind","event_type","operator"]},"SegmentTrackingConsentRuleInput":{"type":"object","properties":{"kind":{"type":"string","const":"tracking_consent"},"value":{"type":"boolean"}},"required":["kind","value"]},"SegmentConsentRuleInput":{"type":"object","properties":{"kind":{"type":"string","const":"consent"},"purpose":{"type":"string","pattern":"^[a-z][a-z0-9_]{2,40}$"},"status":{"type":"string","enum":["granted","refused","withdrawn","none"],"description":"`none`: no act recorded"}},"required":["kind","purpose","status"]},"SegmentInactivityRuleInput":{"type":"object","properties":{"kind":{"type":"string","const":"inactivity"},"operator":{"type":"string","enum":["is_inactive","is_active"]}},"required":["kind","operator"]},"SegmentScoreRuleInput":{"type":"object","properties":{"kind":{"type":"string","const":"score"},"operator":{"type":"string","enum":["gt","gte","lt","lte","between"]},"value":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"array","prefixItems":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}],"items":false,"minItems":2,"maxItems":2}]}},"required":["kind","operator","value"]},"SegmentGroupRuleInput":{"type":"object","properties":{"kind":{"type":"string","const":"group"},"op":{"type":"string","enum":["and","or"]},"rules":{"minItems":1,"maxItems":50,"type":"array","items":{"$ref":"#/components/schemas/SegmentRuleInput"}}},"required":["kind","op","rules"]},"SegmentRuleInput":{"oneOf":[{"$ref":"#/components/schemas/SegmentGroupRuleInput"},{"$ref":"#/components/schemas/SegmentAttributeRuleInput"},{"$ref":"#/components/schemas/SegmentStatusRuleInput"},{"$ref":"#/components/schemas/SegmentListRuleInput"},{"$ref":"#/components/schemas/SegmentEventRuleInput"},{"$ref":"#/components/schemas/SegmentTrackingConsentRuleInput"},{"$ref":"#/components/schemas/SegmentConsentRuleInput"},{"$ref":"#/components/schemas/SegmentInactivityRuleInput"},{"$ref":"#/components/schemas/SegmentScoreRuleInput"}]},"ProblemInput":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"detail":{"type":"string"},"code":{"type":"string"},"request_id":{"type":"string"},"errors":{}},"required":["type","title","status","code","request_id"],"additionalProperties":{},"description":"Error in RFC 9457 format (Problem Details)"},"ConsentInput":{"type":"object","properties":{"granted":{"type":"boolean"},"at":{"type":["string","null"]},"source":{"type":["string","null"]}},"required":["granted","at","source"]},"SequenceTriggerInput":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"list"},"list_id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"}},"required":["type","list_id"]},{"type":"object","properties":{"type":{"type":"string","const":"segment"},"segment_id":{"type":"string","pattern":"^seg_[0-9a-z]{26}$","example":"seg_0123456789abcdefghjkmnpqrs"}},"required":["type","segment_id"]},{"type":"object","properties":{"type":{"type":"string","const":"api"}},"required":["type"]}]},"SequenceBranchInput":{"oneOf":[{"type":"object","properties":{"action":{"type":"string","const":"continue"}},"required":["action"]},{"type":"object","properties":{"action":{"type":"string","const":"goto"},"step_id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["action","step_id"]},{"type":"object","properties":{"action":{"type":"string","const":"exit"}},"required":["action"]}]},"SendStepInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"type":{"type":"string","const":"send"},"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"next":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["id","type","template_id"]},"WaitStepInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"type":{"type":"string","const":"wait"},"duration":{"type":"object","properties":{"value":{"type":"integer","exclusiveMinimum":0,"maximum":100000},"unit":{"type":"string","enum":["minutes","hours","days"]}},"required":["value","unit"]},"business_days":{"type":"boolean"},"send_window":{"type":"object","properties":{"start":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},"end":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"}},"required":["start","end"]},"next":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["id","type","duration"]},"ConditionStepInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"type":{"type":"string","const":"condition"},"segment_id":{"type":"string","pattern":"^seg_[0-9a-z]{26}$","example":"seg_0123456789abcdefghjkmnpqrs"},"if_match":{"$ref":"#/components/schemas/SequenceBranchInput"},"else":{"$ref":"#/components/schemas/SequenceBranchInput"},"next":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["id","type","segment_id","if_match","else"]},"WebhookStepInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"type":{"type":"string","const":"webhook"},"webhook_id":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"},"next":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["id","type","webhook_id"]},"AbTestStepInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"type":{"type":"string","const":"ab_test"},"variants":{"minItems":2,"maxItems":5,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"weight":{"type":"integer","minimum":1,"maximum":100}},"required":["id","template_id","weight"]}},"winner":{"type":"object","properties":{"metric":{"type":"string","enum":["opened","clicked","delivered"]},"evaluate_after":{"type":"object","properties":{"value":{"type":"integer","exclusiveMinimum":0,"maximum":1000},"unit":{"type":"string","enum":["hours","days"]}},"required":["value","unit"]},"min_sample":{"type":"integer","minimum":10,"maximum":9007199254740991}},"required":["metric","evaluate_after","min_sample"]},"winner_variant_id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"decided_at":{"type":"string"},"next":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["id","type","variants"]},"SplitStepInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"type":{"type":"string","const":"split"},"branches":{"minItems":2,"maxItems":5,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"start":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["id","start"]}},"join":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"next":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["id","type","branches"]},"SequenceStepInput":{"oneOf":[{"$ref":"#/components/schemas/SendStepInput"},{"$ref":"#/components/schemas/WaitStepInput"},{"$ref":"#/components/schemas/ConditionStepInput"},{"$ref":"#/components/schemas/WebhookStepInput"},{"$ref":"#/components/schemas/AbTestStepInput"},{"$ref":"#/components/schemas/SplitStepInput"}]},"ReenrollmentPolicyInput":{"oneOf":[{"type":"object","properties":{"policy":{"type":"string","const":"forbidden"}},"required":["policy"]},{"type":"object","properties":{"policy":{"type":"string","const":"after_delay"},"delay_seconds":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["policy","delay_seconds"]}]},"WebhookCreateRequestInput":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"format":"uri"},"events":{"minItems":1,"maxItems":7,"type":"array","items":{"type":"string","enum":["contact.unsubscribed","contact.bounced","contact.complained","enrollment.started","enrollment.completed","enrollment.exited","message.delivered"]}},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]}},"required":["url","events"]},"WebhookPatchRequestInput":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"format":"uri"},"events":{"minItems":1,"maxItems":7,"type":"array","items":{"type":"string","enum":["contact.unsubscribed","contact.bounced","contact.complained","enrollment.started","enrollment.completed","enrollment.exited","message.delivered"]}},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"status":{"description":"Reactivates an automatically disabled webhook","type":"string","const":"active"}}},"WebhookInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"description":{"type":["string","null"]},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"consecutive_failures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","url","events","description","status","disabled_reason","consecutive_failures","created_at","updated_at"]},"WebhookDeliveryInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^wdl_[0-9a-z]{26}$","example":"wdl_0123456789abcdefghjkmnpqrs"},"webhook_id":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"},"event_type":{"type":"string"},"event_id":{"type":["string","null"]},"status":{"type":"string","enum":["pending","delivered","failed","exhausted"]},"attempts":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"last_status_code":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"last_error":{"type":["string","null"]},"next_attempt_at":{"type":["string","null"]},"delivered_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","webhook_id","event_type","event_id","status","attempts","last_status_code","last_error","next_attempt_at","delivered_at","created_at"]},"ConsentActRequestInput":{"type":"object","properties":{"purpose":{"type":"string","pattern":"^[a-z][a-z0-9_]{2,40}$","description":"Purpose. Known: marketing_email, tracking_open_email, tracking_click_email, precontractual_contact, marketing_sms, marketing_whatsapp, marketing_push, transactional_sms, transactional_whatsapp; any other key is recorded with no effect."},"status":{"type":"string","enum":["granted","refused","withdrawn"]},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z","description":"Date of the act (ISO 8601). Each act has its own."},"source":{"type":"string","minLength":1,"maxLength":200,"description":"Source of the act (e.g. \"form:quote-request\", \"preference_center\")"},"proof_url":{"description":"Full URL of the proof (dated capture, archive…)","anyOf":[{"type":"string","maxLength":2000,"format":"uri"},{"type":"null"}]},"form_url":{"anyOf":[{"type":"string","maxLength":2000,"format":"uri"},{"type":"null"}]},"ip":{"description":"IP address of the person at the time of the act","anyOf":[{"type":"string","maxLength":45},{"type":"null"}]},"label":{"description":"Exact wording of the box ticked / notice read","anyOf":[{"type":"string","maxLength":1000},{"type":"null"}]},"list_id":{"description":"Target list (marketing purposes)","anyOf":[{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},{"type":"null"}]}},"required":["purpose","status","at","source"]},"ConsentStateInput":{"type":"object","properties":{"status":{"type":"string","enum":["granted","refused","withdrawn"]},"at":{"type":"string"},"source":{"type":"string"},"proof_url":{"type":["string","null"]},"label":{"type":["string","null"]},"list_id":{"type":["string","null"]},"first_granted_at":{"type":["string","null"]},"withdrawn_at":{"type":["string","null"]}},"required":["status","at","source","proof_url","label","list_id","first_granted_at","withdrawn_at"]},"ConsentResultInput":{"type":"object","properties":{"purpose":{"type":"string"},"status":{"type":"string","enum":["granted","refused","withdrawn"]},"outcome":{"type":"string","enum":["applied","recorded_only","superseded","superseded_by_unsubscribe","contact_suppressed"]}},"required":["purpose","status","outcome"]},"ConsentActInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^cns_[0-9a-z]{26}$","example":"cns_0123456789abcdefghjkmnpqrs"},"purpose":{"type":"string"},"status":{"type":"string","enum":["granted","refused","withdrawn"]},"occurred_at":{"type":"string"},"source":{"type":"string"},"proof_url":{"type":["string","null"]},"form_url":{"type":["string","null"]},"ip":{"type":["string","null"]},"label":{"type":["string","null"]},"list_id":{"type":["string","null"]},"outcome":{"type":"string"},"recorded_at":{"type":"string"}},"required":["id","purpose","status","occurred_at","source","proof_url","form_url","ip","label","list_id","outcome","recorded_at"]},"EventInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^evt_[0-9a-z]{26}$","example":"evt_0123456789abcdefghjkmnpqrs"},"type":{"type":"string"},"contact_id":{"type":["string","null"]},"message_id":{"type":["string","null"]},"sequence_id":{"type":["string","null"]},"step_id":{"type":["string","null"]},"list_id":{"type":["string","null"]},"template_id":{"type":["string","null"]},"enrollment_id":{"type":["string","null"]},"payload":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"occurred_at":{"type":"string"}},"required":["id","type","contact_id","message_id","sequence_id","step_id","list_id","template_id","enrollment_id","payload","occurred_at"]},"TransactionalSendRequestInput":{"type":"object","properties":{"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs","description":"Template of type `transactional`"},"to":{"anyOf":[{"type":"object","properties":{"contact_id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"}},"required":["contact_id"]},{"type":"object","properties":{"email":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"first_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"last_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"attributes":{"type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{"type":["string","number","boolean"]}}},"required":["email"]}],"description":"Recipient: an existing contact, or a free address (no contact created, address not persisted)"},"variables":{"description":"Rendering variable overrides (e.g. `order_id`, `reset_link`); `unsubscribe_url` is reserved","type":"object","propertyNames":{"type":"string","maxLength":100},"additionalProperties":{"type":"string","maxLength":4000}}},"required":["template_id","to"]},"TrackingDomainInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^trk_[0-9a-z]{26}$","example":"trk_0123456789abcdefghjkmnpqrs"},"domain":{"type":"string"},"status":{"type":"string","enum":["pending","verified","failed"]},"base_url":{"type":"string","description":"Base of the public URLs (pixels, clicks, unsubscribe) when the domain is verified"},"dns_records":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","const":"CNAME"},"name":{"type":"string"},"value":{"type":"string"}},"required":["type","name","value"]}},"verified_at":{"type":["string","null"]},"last_checked_at":{"type":["string","null"]},"last_check_error":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","domain","status","base_url","dns_records","verified_at","last_checked_at","last_check_error","created_at"]},"TenantQuotasInput":{"type":"object","properties":{"emails_per_day":{"type":"integer","minimum":0,"maximum":9007199254740991},"max_contacts":{"type":"integer","minimum":0,"maximum":9007199254740991},"api_calls_per_minute":{"type":"integer","minimum":1,"maximum":9007199254740991}},"required":["emails_per_day","max_contacts","api_calls_per_minute"]},"TenantSettingsInput":{"type":"object","properties":{"timezone":{"type":"string","minLength":1,"maxLength":64},"send_rate_per_second":{"type":"number","exclusiveMinimum":0},"soft_bounce_threshold":{"type":"integer","minimum":1,"maximum":9007199254740991},"allowed_reply_to":{"maxItems":50,"type":"array","items":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"bounce_rate_alert_threshold":{"type":"number","minimum":0,"maximum":1},"complaint_rate_alert_threshold":{"type":"number","minimum":0,"maximum":1},"inactivity":{"description":"F-STA-05: inactive contacts handling, based solely on `last_open_date` (F-STA-04)","anyOf":[{"type":"object","properties":{"after_days":{"type":"integer","minimum":30,"maximum":9007199254740991,"description":"No known open for N days (≥ 30)"},"min_sent":{"type":"integer","minimum":1,"maximum":9007199254740991,"description":"After at least N sends performed"},"action":{"type":"string","const":"exclude"}},"required":["after_days","min_sent","action"]},{"type":"null"}]},"mta_outbound_ip":{"anyOf":[{"type":"string","maxLength":45},{"type":"null"}]},"retention":{"description":"NFR-RGPD-08: retention period overrides (days); absent = platform defaults","anyOf":[{"type":"object","properties":{"events_days":{"type":"integer","minimum":30,"maximum":9007199254740991},"audit_days":{"type":"integer","minimum":30,"maximum":9007199254740991},"webhook_deliveries_days":{"type":"integer","minimum":7,"maximum":9007199254740991}}},{"type":"null"}]},"scoring":{"description":"F-SEG-04: lead scoring rules; absent/null = scoring disabled","anyOf":[{"$ref":"#/components/schemas/ScoringRulesInput"},{"type":"null"}]}},"required":["timezone","send_rate_per_second","soft_bounce_threshold","allowed_reply_to","bounce_rate_alert_threshold","complaint_rate_alert_threshold"]},"EffectiveRetentionInput":{"type":"object","properties":{"events_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"audit_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"webhook_deliveries_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sandbox_captures_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"message_links_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["events_days","audit_days","webhook_deliveries_days","sandbox_captures_days","message_links_days"],"description":"Effective retention periods (defaults merged)"},"TenantInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"status":{"type":"string","enum":["active","suspended","deleted"]},"quotas":{"$ref":"#/components/schemas/TenantQuotasInput"},"settings":{"$ref":"#/components/schemas/TenantSettingsInput"},"sending_paused":{"type":"boolean"},"sending_paused_reason":{"type":["string","null"]},"slug":{"description":"Platform tracking subdomain `<slug>.<TRACKING_PLATFORM_SUFFIX>` (ADR-0007)","type":["string","null"]},"tracking_base_url":{"type":"string","description":"Base URL of the public links of upcoming sends (custom, platform or global)"},"tracking_base_kind":{"type":"string","enum":["custom","platform","global"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"deleted_at":{"type":["string","null"]}},"required":["id","name","status","quotas","settings","sending_paused","sending_paused_reason","slug","tracking_base_url","tracking_base_kind","created_at","updated_at","deleted_at"]},"TenantUsageInput":{"type":"object","properties":{"emails_today":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"contacts_total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"api_keys_active":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["emails_today","contacts_total","api_keys_active"]},"ApiKeyInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^key_[0-9a-z]{26}$","example":"key_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"prefix":{"type":"string"},"mode":{"type":"string","enum":["live","test"]},"scopes":{"type":"array","items":{"type":"string"}},"allowed_ips":{"type":"array","items":{"type":"string"},"description":"NFR-SEC-06: allowed IPs / CIDRs; empty = no restriction"},"status":{"type":"string","enum":["active","revoked"]},"last_used_at":{"type":["string","null"]},"created_at":{"type":"string"},"revoked_at":{"type":["string","null"]}},"required":["id","name","prefix","mode","scopes","allowed_ips","status","last_used_at","created_at","revoked_at"]},"DnsRecordInput":{"type":"object","properties":{"type":{"type":"string","const":"TXT"},"name":{"type":"string"},"value":{"type":"string"},"purpose":{"type":"string","enum":["dkim","spf","dmarc"]},"note":{"type":"string"}},"required":["type","name","value","purpose"]},"SendingDomainInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^dom_[0-9a-z]{26}$","example":"dom_0123456789abcdefghjkmnpqrs"},"domain":{"type":"string"},"status":{"type":"string","enum":["pending","verified","failed"]},"dkim_selector":{"type":"string"},"spf_verified":{"type":"boolean"},"dkim_verified":{"type":"boolean"},"dmarc_verified":{"type":"boolean"},"last_checked_at":{"type":["string","null"]},"last_check_error":{"type":["string","null"]},"dns_records":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordInput"}},"warmup":{"anyOf":[{"type":"object","properties":{"started_at":{"type":"string"},"day":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"daily_limit":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"null = plan complete, unlimited"},"sent_today":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["started_at","day","daily_limit","sent_today"]},{"type":"null"}],"description":"F-SND-06: warm-up in progress (null otherwise)"},"created_at":{"type":"string"}},"required":["id","domain","status","dkim_selector","spf_verified","dkim_verified","dmarc_verified","last_checked_at","last_check_error","dns_records","warmup","created_at"]},"AttributeDefinitionInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^atr_[0-9a-z]{26}$","example":"atr_0123456789abcdefghjkmnpqrs"},"key":{"type":"string"},"label":{"type":["string","null"]},"type":{"type":"string","enum":["text","number","boolean","date"]},"created_at":{"type":"string"}},"required":["id","key","label","type","created_at"]},"AttributeDefinitionRequestInput":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$","description":"Key used in `attributes` and in segmentation (`attributes.<key>`)"},"type":{"type":"string","enum":["text","number","boolean","date"]},"label":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]}},"required":["key","type"]},"AuditLogInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^aud_[0-9a-z]{26}$","example":"aud_0123456789abcdefghjkmnpqrs"},"tenant_id":{"type":["string","null"]},"actor":{"type":"string","enum":["tenant","operator"]},"api_key_id":{"type":["string","null"]},"key_prefix":{"type":["string","null"]},"method":{"type":"string"},"path":{"type":"string"},"route":{"type":["string","null"]},"resource_id":{"type":["string","null"]},"status_code":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"request_id":{"type":"string"},"ip":{"type":["string","null"]},"occurred_at":{"type":"string"}},"required":["id","tenant_id","actor","api_key_id","key_prefix","method","path","route","resource_id","status_code","request_id","ip","occurred_at"]},"CampaignAudienceInput":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"list"},"list_id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"}},"required":["type","list_id"]},{"type":"object","properties":{"type":{"type":"string","const":"segment"},"segment_id":{"type":"string","pattern":"^seg_[0-9a-z]{26}$","example":"seg_0123456789abcdefghjkmnpqrs"}},"required":["type","segment_id"]}]},"CampaignCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs","description":"Template of type `marketing`"},"audience":{"$ref":"#/components/schemas/CampaignAudienceInput"},"scheduled_at":{"description":"Send date (UTC). Absent: immediate send on `POST …/schedule`","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"}},"required":["name","template_id","audience"]},"CampaignPatchInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"audience":{"$ref":"#/components/schemas/CampaignAudienceInput"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"},{"type":"null"}]}}},"CampaignInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^cmp_[0-9a-z]{26}$","example":"cmp_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"audience":{"$ref":"#/components/schemas/CampaignAudienceInput"},"mode":{"type":"string","enum":["live","test"],"description":"Send mode inherited from the key that created the campaign: `test` = captured (Sandbox), never sent."},"status":{"type":"string","enum":["draft","scheduled","running","completed","cancelled","failed"]},"scheduled_at":{"type":["string","null"]},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"audience_count":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"queued_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"last_error":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","template_id","audience","mode","status","scheduled_at","started_at","completed_at","audience_count","queued_count","skipped_count","last_error","created_at","updated_at"]},"CampaignDetailInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^cmp_[0-9a-z]{26}$","example":"cmp_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"audience":{"$ref":"#/components/schemas/CampaignAudienceInput"},"mode":{"type":"string","enum":["live","test"],"description":"Send mode inherited from the key that created the campaign: `test` = captured (Sandbox), never sent."},"status":{"type":"string","enum":["draft","scheduled","running","completed","cancelled","failed"]},"scheduled_at":{"type":["string","null"]},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"audience_count":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"queued_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"last_error":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"stats":{"type":"object","properties":{"sent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_hard":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_soft":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"complained":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unsubscribed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"performance":{"type":"object","properties":{"consented_population":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"opened":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"clicked":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"open_rate":{"type":["number","null"]},"click_rate":{"type":["number","null"]},"note":{"type":"string"}},"required":["consented_population","opened","clicked","open_rate","click_rate","note"]}},"required":["sent","delivered","bounced_hard","bounced_soft","complained","unsubscribed","failed","performance"],"description":"Campaign aggregates since its creation (stats_daily)"}},"required":["id","name","template_id","audience","mode","status","scheduled_at","started_at","completed_at","audience_count","queued_count","skipped_count","last_error","created_at","updated_at","stats"]},"TrackingConsentInput":{"type":"object","properties":{"granted":{"type":"boolean"},"at":{"type":["string","null"]},"source":{"type":["string","null"]},"withdrawn_at":{"type":["string","null"]}},"required":["granted","at","source","withdrawn_at"]},"ContactInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"email":{"type":"string"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"language":{"type":["string","null"]},"source":{"type":["string","null"]},"status":{"type":"string","enum":["active","unsubscribed","bounced","complained","suppressed"]},"attributes":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"consents":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/components/schemas/ConsentStateInput"},"description":"Current state per consent purpose (ADR-0005)"},"optin_consent":{"description":"Derived from the `marketing_email` purpose","$ref":"#/components/schemas/ConsentInput"},"tracking_consent":{"description":"Derived from the `tracking_open_email` purpose","$ref":"#/components/schemas/TrackingConsentInput"},"last_open_date":{"description":"Deliverability (F-STA-04): day of last open, overwritten","type":["string","null"]},"score":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Lead scoring (F-SEG-04): 0 when scoring is disabled"},"score_updated_at":{"type":["string","null"]},"unsubscribed_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","email","first_name","last_name","language","source","status","attributes","consents","optin_consent","tracking_consent","last_open_date","score","score_updated_at","unsubscribed_at","created_at","updated_at"]},"ContactSubscriptionInput":{"type":"object","properties":{"list_id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"list_name":{"type":"string"},"status":{"type":"string","enum":["subscribed","unsubscribed"]},"source":{"type":["string","null"]},"subscribed_at":{"type":"string"},"unsubscribed_at":{"type":["string","null"]}},"required":["list_id","list_name","status","source","subscribed_at","unsubscribed_at"]},"ContactEnrollmentSummaryInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^enr_[0-9a-z]{26}$","example":"enr_0123456789abcdefghjkmnpqrs"},"sequence_id":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"status":{"type":"string","enum":["active","completed","exited"]},"current_step_id":{"type":["string","null"]},"next_run_at":{"type":["string","null"]},"started_at":{"type":"string"},"ended_at":{"type":["string","null"]},"exit_reason":{"type":["string","null"]}},"required":["id","sequence_id","status","current_step_id","next_run_at","started_at","ended_at","exit_reason"]},"ContactDetailInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"email":{"type":"string"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"language":{"type":["string","null"]},"source":{"type":["string","null"]},"status":{"type":"string","enum":["active","unsubscribed","bounced","complained","suppressed"]},"attributes":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"consents":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/components/schemas/ConsentStateInput"},"description":"Current state per consent purpose (ADR-0005)"},"optin_consent":{"description":"Derived from the `marketing_email` purpose","$ref":"#/components/schemas/ConsentInput"},"tracking_consent":{"description":"Derived from the `tracking_open_email` purpose","$ref":"#/components/schemas/TrackingConsentInput"},"last_open_date":{"description":"Deliverability (F-STA-04): day of last open, overwritten","type":["string","null"]},"score":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Lead scoring (F-SEG-04): 0 when scoring is disabled"},"score_updated_at":{"type":["string","null"]},"unsubscribed_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"lists":{"type":"array","items":{"$ref":"#/components/schemas/ContactSubscriptionInput"}},"enrollments":{"type":"array","items":{"$ref":"#/components/schemas/ContactEnrollmentSummaryInput"},"description":"Active enrollments"},"last_event":{"anyOf":[{"type":"object","properties":{"type":{"type":"string"},"occurred_at":{"type":"string"}},"required":["type","occurred_at"]},{"type":"null"}]}},"required":["id","email","first_name","last_name","language","source","status","attributes","consents","optin_consent","tracking_consent","last_open_date","score","score_updated_at","unsubscribed_at","created_at","updated_at","lists","enrollments","last_event"]},"ContactUpsertRequestInput":{"type":"object","properties":{"email":{"type":"string","minLength":3,"maxLength":320},"first_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"last_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"language":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}]},"source":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"attributes":{"description":"Custom attributes; `null` removes","type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{}},"consents":{"maxItems":20,"type":"array","items":{"$ref":"#/components/schemas/ConsentActRequestInput"},"description":"Consent acts: at most one per purpose and per call"},"optin_consent":{"description":"Deprecated: equivalent to a `marketing_email` act","type":"object","properties":{"granted":{"type":"boolean"},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z","description":"Proof timestamp"},"source":{"type":"string","minLength":1,"maxLength":200,"description":"Proof source (e.g. \"form:landing-2026-09\", \"import:attestation\")"}},"required":["granted","at","source"]},"tracking_consent":{"description":"Deprecated: equivalent to a `tracking_open_email` act","type":"object","properties":{"granted":{"type":"boolean"},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z","description":"Proof timestamp"},"source":{"type":"string","minLength":1,"maxLength":200,"description":"Proof source (e.g. \"form:landing-2026-09\", \"import:attestation\")"}},"required":["granted","at","source"]},"subscriptions":{"description":"Subscriptions to perform in the same call","maxItems":20,"type":"array","items":{"type":"object","properties":{"list_id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"source":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]}},"required":["list_id"]}}},"required":["email"]},"ContactPatchRequestInput":{"type":"object","properties":{"first_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"last_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"language":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}]},"source":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"attributes":{"description":"Custom attributes; `null` removes","type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{}},"consents":{"maxItems":20,"type":"array","items":{"$ref":"#/components/schemas/ConsentActRequestInput"},"description":"Consent acts: at most one per purpose and per call"},"optin_consent":{"description":"Deprecated: equivalent to a `marketing_email` act","type":"object","properties":{"granted":{"type":"boolean"},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z","description":"Proof timestamp"},"source":{"type":"string","minLength":1,"maxLength":200,"description":"Proof source (e.g. \"form:landing-2026-09\", \"import:attestation\")"}},"required":["granted","at","source"]},"tracking_consent":{"description":"Deprecated: equivalent to a `tracking_open_email` act","type":"object","properties":{"granted":{"type":"boolean"},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z","description":"Proof timestamp"},"source":{"type":"string","minLength":1,"maxLength":200,"description":"Proof source (e.g. \"form:landing-2026-09\", \"import:attestation\")"}},"required":["granted","at","source"]}}},"EnrollmentStepLogInput":{"type":"object","properties":{"step_id":{"type":"string"},"step_type":{"type":"string"},"outcome":{"type":"string"},"detail":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"occurred_at":{"type":"string"}},"required":["step_id","step_type","outcome","detail","occurred_at"]},"EnrollmentInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^enr_[0-9a-z]{26}$","example":"enr_0123456789abcdefghjkmnpqrs"},"sequence_id":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"sequence_version":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"contact_id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"status":{"type":"string","enum":["active","completed","exited"]},"current_step_id":{"type":["string","null"]},"next_run_at":{"description":"Next due time (wait step), ISO 8601 UTC","type":["string","null"]},"trigger":{"type":"object","properties":{"type":{"type":"string","enum":["list","segment","api","branch"]},"ref":{"type":["string","null"]}},"required":["type","ref"]},"parent_enrollment_id":{"anyOf":[{"type":"string","pattern":"^enr_[0-9a-z]{26}$","example":"enr_0123456789abcdefghjkmnpqrs"},{"type":"null"}]},"branch_path":{"type":["string","null"]},"exit_reason":{"type":["string","null"]},"started_at":{"type":"string"},"ended_at":{"type":["string","null"]},"history":{"type":"array","items":{"$ref":"#/components/schemas/EnrollmentStepLogInput"}},"children":{"description":"Parallel branches of this main enrollment","type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^enr_[0-9a-z]{26}$","example":"enr_0123456789abcdefghjkmnpqrs"},"branch_path":{"type":["string","null"]},"status":{"type":"string","enum":["active","completed","exited"]},"current_step_id":{"type":["string","null"]},"exit_reason":{"type":["string","null"]}},"required":["id","branch_path","status","current_step_id","exit_reason"]}}},"required":["id","sequence_id","sequence_version","contact_id","status","current_step_id","next_run_at","trigger","parent_enrollment_id","branch_path","exit_reason","started_at","ended_at"]},"ExportParamsInput":{"type":"object","properties":{"from":{"description":"Period start (UTC day, inclusive) — on-demand export","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"description":"Period end (UTC day, inclusive) — on-demand export","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"sequence_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"}},"list_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"}},"types":{"description":"Event types (kind `events`)","maxItems":30,"type":"array","items":{"type":"string","minLength":1,"maxLength":60}},"bom":{"description":"CSV: prefix with a UTF-8 BOM (Excel)","type":"boolean"}}},"ExportDeliveryInput":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"download"}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"webhook"},"webhook_id":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"}},"required":["type","webhook_id"]}]},"ExportScheduleCreateRequestInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["stats_overview","stats_sequences","stats_lists","events"]},"format":{"default":"json","type":"string","enum":["json","csv"]},"params":{"default":{},"type":"object","properties":{"sequence_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"}},"list_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"}},"types":{"description":"Event types (kind `events`)","maxItems":30,"type":"array","items":{"type":"string","minLength":1,"maxLength":60}},"bom":{"description":"CSV: prefix with a UTF-8 BOM (Excel)","type":"boolean"}}},"frequency":{"type":"string","enum":["daily","weekly","monthly"]},"hour_utc":{"default":6,"type":"integer","minimum":0,"maximum":23},"day_of":{"default":1,"description":"Weekly: 1 (Monday) to 7 (Sunday); monthly: day of month 1 to 28","type":"integer","minimum":1,"maximum":28},"delivery":{"default":{"type":"download"},"$ref":"#/components/schemas/ExportDeliveryInput"}},"required":["name","kind","frequency"]},"ExportSchedulePatchRequestInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"format":{"type":"string","enum":["json","csv"]},"params":{"type":"object","properties":{"sequence_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"}},"list_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"}},"types":{"description":"Event types (kind `events`)","maxItems":30,"type":"array","items":{"type":"string","minLength":1,"maxLength":60}},"bom":{"description":"CSV: prefix with a UTF-8 BOM (Excel)","type":"boolean"}}},"frequency":{"type":"string","enum":["daily","weekly","monthly"]},"hour_utc":{"type":"integer","minimum":0,"maximum":23},"day_of":{"type":"integer","minimum":1,"maximum":28},"delivery":{"$ref":"#/components/schemas/ExportDeliveryInput"},"status":{"type":"string","enum":["active","paused"]}}},"ExportCreateRequestInput":{"type":"object","properties":{"kind":{"type":"string","enum":["stats_overview","stats_sequences","stats_lists","events"]},"format":{"default":"json","type":"string","enum":["json","csv"]},"params":{"default":{},"$ref":"#/components/schemas/ExportParamsInput"},"delivery":{"default":{"type":"download"},"$ref":"#/components/schemas/ExportDeliveryInput"}},"required":["kind"]},"ExportScheduleInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^exs_[0-9a-z]{26}$","example":"exs_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"kind":{"type":"string","enum":["stats_overview","stats_sequences","stats_lists","events"]},"format":{"type":"string","enum":["json","csv"]},"params":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"frequency":{"type":"string","enum":["daily","weekly","monthly"]},"hour_utc":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"day_of":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivery":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"status":{"type":"string","enum":["active","paused"]},"next_run_at":{"type":["string","null"]},"last_run_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","kind","format","params","frequency","hour_utc","day_of","delivery","status","next_run_at","last_run_at","created_at","updated_at"]},"ExportInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^exp_[0-9a-z]{26}$","example":"exp_0123456789abcdefghjkmnpqrs"},"schedule_id":{"type":["string","null"]},"kind":{"type":"string","enum":["stats_overview","stats_sequences","stats_lists","events"]},"format":{"type":"string","enum":["json","csv"]},"params":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"period":{"anyOf":[{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to"]},{"type":"null"}]},"status":{"type":"string","enum":["pending","running","completed","failed"]},"row_count":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"size_bytes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"sha256":{"type":["string","null"]},"error":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"download_url":{"description":"Present when the export is ready and not expired","type":["string","null"]},"created_at":{"type":"string"},"completed_at":{"type":["string","null"]}},"required":["id","schedule_id","kind","format","params","period","status","row_count","size_bytes","sha256","error","expires_at","download_url","created_at","completed_at"]},"ImportAttestationInput":{"type":"object","properties":{"attested_by":{"type":"string","minLength":1,"maxLength":200,"description":"Person or system attesting (e.g. \"dpo@tenant.com\")"},"statement":{"type":"string","minLength":20,"maxLength":2000,"description":"Statement of lawfulness of the base (consents collected, transitional regime closed, …)"},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z","description":"Attestation timestamp"}},"required":["attested_by","statement","at"]},"ImportReportLineInput":{"type":"object","properties":{"line":{"type":"integer","minimum":1,"maximum":9007199254740991},"status":{"type":"string","enum":["created","updated","failed"]},"code":{"type":"string"},"detail":{"type":"string"}},"required":["line","status"]},"ContactImportInput":{"type":"object","properties":{"id":{"type":"string"},"job_id":{"type":"string"},"status":{"type":"string","enum":["pending","running","completed","failed"]},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"processed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"created":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"updated":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"attestation":{"$ref":"#/components/schemas/ImportAttestationInput"},"report":{"type":"array","items":{"$ref":"#/components/schemas/ImportReportLineInput"},"description":"One entry per processed row; never an e-mail address"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","job_id","status","total","processed","created","updated","failed","attestation","report","created_at","updated_at"]},"ContactImportRequestInput":{"type":"object","properties":{"attestation":{"description":"Mandatory (NFR-RGPD-06): timestamped attestation of the lawfulness of the imported base","$ref":"#/components/schemas/ImportAttestationInput"},"default_source":{"description":"Source applied to rows without `source`","type":"string","maxLength":200},"rows":{"minItems":1,"type":"array","items":{},"description":"Rows in ContactUpsertRequest format (max 10000)"}},"required":["rows"]},"JobInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^job_[0-9a-z]{26}$","example":"job_0123456789abcdefghjkmnpqrs"},"type":{"type":"string"},"status":{"type":"string","enum":["pending","running","completed","failed"]},"progress":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"result":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"error":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","type","status","progress","result","error","created_at","updated_at"]},"ListInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"description":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","description","created_at","updated_at"]},"ListDetailInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"description":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"subscribers_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","description","created_at","updated_at","subscribers_count"]},"ListRequestInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]}},"required":["name"]},"ListSubscriptionInput":{"type":"object","properties":{"list_id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"contact_id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"status":{"type":"string","enum":["subscribed","unsubscribed"]},"source":{"type":["string","null"]},"subscribed_at":{"type":"string"},"unsubscribed_at":{"type":["string","null"]}},"required":["list_id","contact_id","status","source","subscribed_at","unsubscribed_at"]},"ListSubscribeRequestInput":{"type":"object","properties":{"contact_id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"email":{"type":"string","minLength":3,"maxLength":320},"source":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]}}},"MessageInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^msg_[0-9a-z]{26}$","example":"msg_0123456789abcdefghjkmnpqrs"},"kind":{"type":"string","enum":["sequence","test","campaign","transactional"]},"mode":{"type":"string","enum":["live","test"]},"status":{"type":"string"},"contact_id":{"type":["string","null"]},"template_id":{"type":["string","null"]},"sequence_id":{"type":["string","null"]},"campaign_id":{"type":["string","null"]},"subject":{"type":["string","null"]},"attempts":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"last_error":{"type":["string","null"]},"queued_at":{"type":"string"},"sent_at":{"type":["string","null"]},"delivered_at":{"type":["string","null"]},"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^evt_[0-9a-z]{26}$","example":"evt_0123456789abcdefghjkmnpqrs"},"type":{"type":"string"},"occurred_at":{"type":"string"},"payload":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["id","type","occurred_at","payload"]}}},"required":["id","kind","mode","status","contact_id","template_id","sequence_id","campaign_id","subject","attempts","last_error","queued_at","sent_at","delivered_at","events"]},"GenericProviderWebhookInput":{"type":"object","properties":{"events":{"minItems":1,"maxItems":1000,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":200},"type":{"type":"string","enum":["delivered","bounce_hard","bounce_soft","complaint"]},"provider_message_id":{"type":"string","minLength":1,"maxLength":500},"occurred_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"reason":{"type":"string","maxLength":1000}},"required":["id","type","provider_message_id","occurred_at"]}}},"required":["events"]},"SandboxMessageSummaryInput":{"type":"object","properties":{"id":{"type":"string"},"message_id":{"type":"string"},"contact_id":{"type":["string","null"]},"to":{"type":"string"},"from":{"type":"string"},"reply_to":{"type":["string","null"]},"subject":{"type":"string"},"created_at":{"type":"string"}},"required":["id","message_id","contact_id","to","from","reply_to","subject","created_at"]},"SandboxMessageInput":{"type":"object","properties":{"id":{"type":"string"},"message_id":{"type":"string"},"contact_id":{"type":["string","null"]},"to":{"type":"string"},"from":{"type":"string"},"reply_to":{"type":["string","null"]},"subject":{"type":"string"},"created_at":{"type":"string"},"html":{"type":"string"},"text":{"type":["string","null"]},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["id","message_id","contact_id","to","from","reply_to","subject","created_at","html","text","headers"]},"SegmentInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^seg_[0-9a-z]{26}$","example":"seg_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"description":{"type":["string","null"]},"rules":{},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","description","rules","created_at","updated_at"]},"SegmentMemberInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"email":{"type":"string"},"status":{"type":"string"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","email","status","first_name","last_name","created_at"]},"SegmentPreviewRequestInput":{"type":"object","properties":{"rules":{"$ref":"#/components/schemas/SegmentRuleInput"},"limit":{"default":10,"type":"integer","minimum":1,"maximum":50}},"required":["rules"]},"SegmentPreviewInput":{"type":"object","properties":{"total_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sample":{"type":"array","items":{"$ref":"#/components/schemas/SegmentMemberInput"}}},"required":["total_count","sample"]},"SequenceInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["draft","active","paused","archived"]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"trigger":{"$ref":"#/components/schemas/SequenceTriggerInput"},"steps":{"minItems":1,"maxItems":100,"type":"array","items":{"$ref":"#/components/schemas/SequenceStepInput"}},"reenrollment":{"$ref":"#/components/schemas/ReenrollmentPolicyInput"},"exit_on_trigger_segment_exit":{"type":"boolean"},"required_consent_purpose":{"type":"string","pattern":"^[a-z][a-z0-9_]{2,40}$","description":"Consent purpose the contact must have granted to be enrolled and receive the e-mails (`marketing_email` by default, e.g. `precontractual_contact`). A tenant-wide unsubscribe blocks regardless."},"counts":{"type":"object","properties":{"active":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"completed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"exited":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["active","completed","exited"],"description":"Main enrollments per status; always returned, including by the list endpoint."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","description","status","version","trigger","steps","reenrollment","exit_on_trigger_segment_exit","required_consent_purpose","counts","created_at","updated_at"]},"SequenceCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"trigger":{"$ref":"#/components/schemas/SequenceTriggerInput"},"steps":{"minItems":1,"maxItems":100,"type":"array","items":{"$ref":"#/components/schemas/SequenceStepInput"}},"reenrollment":{"default":{"policy":"forbidden"},"$ref":"#/components/schemas/ReenrollmentPolicyInput"},"exit_on_trigger_segment_exit":{"default":false,"type":"boolean"},"required_consent_purpose":{"default":"marketing_email","type":"string","pattern":"^[a-z][a-z0-9_]{2,40}$","description":"Consent purpose the contact must have granted to be enrolled and receive the e-mails (`marketing_email` by default, e.g. `precontractual_contact`). A tenant-wide unsubscribe blocks regardless."}},"required":["name","trigger","steps"]},"SequencePatchInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"trigger":{"$ref":"#/components/schemas/SequenceTriggerInput"},"steps":{"minItems":1,"maxItems":100,"type":"array","items":{"$ref":"#/components/schemas/SequenceStepInput"}},"reenrollment":{"$ref":"#/components/schemas/ReenrollmentPolicyInput"},"exit_on_trigger_segment_exit":{"type":"boolean"},"required_consent_purpose":{"type":"string","pattern":"^[a-z][a-z0-9_]{2,40}$","description":"Consent purpose the contact must have granted to be enrolled and receive the e-mails (`marketing_email` by default, e.g. `precontractual_contact`). A tenant-wide unsubscribe blocks regardless."},"migrate_active_enrollments":{"default":false,"type":"boolean"}}},"EnrollmentCreateInput":{"type":"object","properties":{"contact_id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"}},"required":["contact_id"]},"PerformanceStatsInput":{"type":"object","properties":{"consented_population":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"opened":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"clicked":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"open_rate":{"type":["number","null"]},"click_rate":{"type":["number","null"]},"note":{"type":"string"}},"required":["consented_population","opened","clicked","open_rate","click_rate","note"]},"AggregateInput":{"type":"object","properties":{"sent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_hard":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_soft":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"complained":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unsubscribed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"performance":{"$ref":"#/components/schemas/PerformanceStatsInput"}},"required":["sent","delivered","bounced_hard","bounced_soft","complained","unsubscribed","failed","performance"]},"SuppressionInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^sup_[0-9a-z]{26}$","example":"sup_0123456789abcdefghjkmnpqrs"},"email":{"description":"NULL after GDPR erasure (only the fingerprint remains)","type":["string","null"]},"email_hash":{"type":"string"},"reason":{"type":"string","enum":["unsubscribed","hard_bounce","complaint","manual","erased"]},"detail":{"type":["string","null"]},"source":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","email","email_hash","reason","detail","source","created_at"]},"TemplateTrackingInput":{"type":"object","properties":{"deliverability_pixel":{"default":true,"description":"Deliverability pixel (exempt from consent, NFR-RGPD-02)","type":"boolean"},"performance_pixel":{"default":true,"description":"Performance pixel (inserted only with a valid tracking consent)","type":"boolean"},"click_tracking":{"default":false,"description":"Link rewriting to measure clicks (F-TPL-05): applied only if the contact’s `tracking_click_email` purpose is granted (NFR-RGPD-04)","type":"boolean"}}},"TemplateCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"subject":{"type":"string","minLength":1,"maxLength":998},"html_body":{"type":"string","minLength":1,"description":"Must contain {{unsubscribe_url}} (F-TPL-03)"},"text_body":{"anyOf":[{"type":"string","maxLength":200000},{"type":"null"}]},"from_email":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"from_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"reply_to":{"anyOf":[{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}]},"variable_defaults":{"default":{},"type":"object","propertyNames":{"type":"string","maxLength":100},"additionalProperties":{"type":"string","maxLength":2000}},"tracking":{"default":{"deliverability_pixel":true,"performance_pixel":true,"click_tracking":false},"$ref":"#/components/schemas/TemplateTrackingInput"},"kind":{"default":"marketing","type":"string","enum":["marketing","transactional"],"description":"`marketing`: series and campaigns, unsubscribe link mandatory, pixels according to consent. `transactional`: single service e-mail (`POST /v1/messages`), no unsubscribe link required, no performance pixel nor click tracking."}},"required":["name","subject","html_body","from_email"]},"TemplatePatchInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"subject":{"type":"string","minLength":1,"maxLength":998},"html_body":{"type":"string","minLength":1},"text_body":{"anyOf":[{"type":"string","maxLength":200000},{"type":"null"}]},"from_email":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"from_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"reply_to":{"anyOf":[{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}]},"variable_defaults":{"type":"object","propertyNames":{"type":"string","maxLength":100},"additionalProperties":{"type":"string","maxLength":2000}},"tracking":{"$ref":"#/components/schemas/TemplateTrackingInput"}}},"TemplateInput":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"subject":{"type":"string"},"html_body":{"type":"string"},"text_body":{"type":["string","null"]},"from_email":{"type":"string"},"from_name":{"type":["string","null"]},"reply_to":{"type":["string","null"]},"variable_defaults":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"tracking":{"type":"object","properties":{"deliverability_pixel":{"type":"boolean"},"performance_pixel":{"type":"boolean"},"click_tracking":{"type":"boolean"}},"required":["deliverability_pixel","performance_pixel","click_tracking"]},"kind":{"type":"string","enum":["marketing","transactional"],"description":"`marketing`: series and campaigns, unsubscribe link mandatory, pixels according to consent. `transactional`: single service e-mail (`POST /v1/messages`), no unsubscribe link required, no performance pixel nor click tracking."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","subject","html_body","text_body","from_email","from_name","reply_to","variable_defaults","tracking","kind","created_at","updated_at"]},"FictiveContactInput":{"type":"object","properties":{"email":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"first_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"last_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"language":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}]},"source":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"attributes":{"default":{},"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":["string","number","boolean","null"]}},"tracking_consent":{"default":false,"description":"Simulates a valid tracking consent","type":"boolean"},"click_consent":{"default":false,"description":"Simulates the `tracking_click_email` purpose as granted","type":"boolean"}},"required":["email"]},"TemplateRenderRequestInput":{"type":"object","properties":{"contact_id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"contact":{"$ref":"#/components/schemas/FictiveContactInput"}}},"TemplateRenderResultInput":{"type":"object","properties":{"subject":{"type":"string"},"html":{"type":"string"},"text":{"type":["string","null"]},"warnings":{"type":"array","items":{"type":"string"}},"tracking":{"type":"object","properties":{"deliverability_pixel":{"type":"boolean"},"performance_pixel":{"type":"boolean"},"click_tracking":{"type":"boolean","description":"Click tracking would apply to a real send to this contact"}},"required":["deliverability_pixel","performance_pixel","click_tracking"]},"tracking_consented":{"type":"boolean"},"click_tracking_applied":{"type":"boolean","const":false,"description":"In preview, links are never rewritten (no message, no database write)"}},"required":["subject","html","text","warnings","tracking","tracking_consented","click_tracking_applied"]},"ContactExportInput":{"type":"object","properties":{"exported_at":{"type":"string"},"contact":{"$ref":"#/components/schemas/ContactInput"},"subscriptions":{"type":"array","items":{"$ref":"#/components/schemas/ContactSubscriptionInput"}},"enrollments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^enr_[0-9a-z]{26}$","example":"enr_0123456789abcdefghjkmnpqrs"},"sequence_id":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"status":{"type":"string","enum":["active","completed","exited"]},"current_step_id":{"type":["string","null"]},"next_run_at":{"type":["string","null"]},"started_at":{"type":"string"},"ended_at":{"type":["string","null"]},"exit_reason":{"type":["string","null"]},"sequence_version_id":{"type":"string","pattern":"^sqv_[0-9a-z]{26}$","example":"sqv_0123456789abcdefghjkmnpqrs"},"trigger_type":{"type":"string"},"step_logs":{"type":"array","items":{"type":"object","properties":{"step_id":{"type":"string"},"step_type":{"type":"string"},"outcome":{"type":"string"},"detail":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"occurred_at":{"type":"string"}},"required":["step_id","step_type","outcome","detail","occurred_at"]}}},"required":["id","sequence_id","status","current_step_id","next_run_at","started_at","ended_at","exit_reason","sequence_version_id","trigger_type","step_logs"]}},"consent_acts":{"type":"array","items":{"$ref":"#/components/schemas/ConsentActInput"}},"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^evt_[0-9a-z]{26}$","example":"evt_0123456789abcdefghjkmnpqrs"},"type":{"type":"string"},"occurred_at":{"type":"string"},"message_id":{"type":["string","null"]},"sequence_id":{"type":["string","null"]},"list_id":{"type":["string","null"]},"payload":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["id","type","occurred_at","message_id","sequence_id","list_id","payload"]}}},"required":["exported_at","contact","subscriptions","enrollments","consent_acts","events"]},"SuppressionRequestInput":{"type":"object","properties":{"email":{"type":"string","minLength":3,"maxLength":320},"reason":{"type":"string","minLength":1,"maxLength":500},"source":{"type":"string","maxLength":200}},"required":["email","reason"]},"RetentionPurgeSummaryInput":{"type":"object","properties":{"tenants":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"totals":{"type":"object","properties":{"events":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"audit_logs":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"webhook_deliveries":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sandbox_captures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"message_links":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["events","audit_logs","webhook_deliveries","sandbox_captures","message_links"]},"global":{"type":"object","properties":{"idempotency_keys":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"operator_audit_logs":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["idempotency_keys","operator_audit_logs"]},"started_at":{"type":"string"},"finished_at":{"type":"string"}},"required":["tenants","totals","global","started_at","finished_at"]},"TrackingDomainCreateRequestInput":{"type":"object","properties":{"domain":{"type":"string","minLength":3,"maxLength":253}},"required":["domain"]},"MtaStatusInput":{"type":"object","properties":{"enabled":{"type":"boolean"},"smarthost":{"type":["string","null"]},"tls":{"type":"string","enum":["opportunistic","require"]},"mta_sts":{"type":"boolean"},"outbound_ips":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"helo":{"type":"string"}},"required":["address","helo"]}},"local_addresses":{"type":"array","items":{"type":"string"}},"pool":{"type":"object","properties":{"enabled":{"type":"boolean"},"connections":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"total":{"type":"number"},"idle":{"type":"number"},"busy":{"type":"number"},"waiting":{"type":"number"}},"required":["key","total","idle","busy","waiting"]}}},"required":["enabled","connections"]},"deferred":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"until":{"type":["string","null"]},"ttl_seconds":{"type":["number","null"]}},"required":["key","until","ttl_seconds"]}},"rates":{"type":"array","items":{"type":"object","properties":{"provider":{"type":"string"},"ip":{"type":"string"},"minute":{"type":"string"},"count":{"type":"number"},"limit":{"type":["number","null"]}},"required":["provider","ip","minute","count","limit"]}},"limits":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"ips":{"description":"Outbound IPs: per-IP warm-up and provider families for which the IP is degraded (ADR-0008)","type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"helo":{"type":"string"},"warmup":{"anyOf":[{"type":"object","properties":{"started_at":{"type":"string"},"day":{"type":"number"},"daily_limit":{"type":["number","null"]},"sent_today":{"type":"number"}},"required":["started_at","day","daily_limit","sent_today"]},{"type":"null"}]},"health":{"type":"object","properties":{"degraded_for":{"type":"array","items":{"type":"string"}}},"required":["degraded_for"]}},"required":["address","helo","warmup","health"]}},"selfcheck":{"description":"DNS self-check (PTR, FCrDNS, bounce domain MX, SPF), cached 10 min","anyOf":[{"type":"object","properties":{"checked_at":{"type":"string"},"results":{"type":"array","items":{"type":"object","properties":{"check":{"type":"string"},"ok":{"type":"boolean"},"detail":{"type":"string"}},"required":["check","ok","detail"]}}},"required":["checked_at","results"]},{"type":"null"}]}},"required":["enabled"]},"TemplateTestSendRequestInput":{"type":"object","properties":{"to":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"contact_id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"}},"required":["to"]},"SandboxEventRequestInput":{"type":"object","properties":{"message_id":{"type":"string","pattern":"^msg_[0-9a-z]{26}$","example":"msg_0123456789abcdefghjkmnpqrs"},"type":{"type":"string","enum":["delivered","bounce_hard","bounce_soft","complaint"]},"reason":{"type":"string","maxLength":500}},"required":["message_id","type"]},"AbTestDecisionInput":{"type":"object","properties":{"variant_id":{"type":"string","minLength":1,"maxLength":40}},"required":["variant_id"]},"ScoringRules":{"type":"object","properties":{"weights":{"type":"object","properties":{"opened":{"type":"integer","minimum":-100,"maximum":100},"clicked":{"type":"integer","minimum":-100,"maximum":100},"delivered":{"type":"integer","minimum":-100,"maximum":100},"bounced_soft":{"type":"integer","minimum":-100,"maximum":100},"unsubscribed":{"type":"integer","minimum":-100,"maximum":100},"complained":{"type":"integer","minimum":-100,"maximum":100},"list.subscribed":{"type":"integer","minimum":-100,"maximum":100},"consent.granted":{"type":"integer","minimum":-100,"maximum":100}},"additionalProperties":false,"description":"Points granted per event type (integers between -100 and 100)"},"decay_per_day":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Points removed per full day without a score update"},"min":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"max":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["weights","decay_per_day","min","max"],"additionalProperties":false},"SegmentAttributeRule":{"type":"object","properties":{"kind":{"type":"string","const":"attribute"},"field":{"type":"string","minLength":1,"maxLength":100},"operator":{"type":"string","enum":["eq","neq","contains","not_contains","starts_with","gt","gte","lt","lte","between","in","not_in","exists","not_exists","before","after","within_last_days","older_than_days"]},"value":{"anyOf":[{"type":["string","number","boolean"]},{"type":"array","items":{"type":["string","number","boolean"]}}]}},"required":["kind","field","operator"],"additionalProperties":false},"SegmentStatusRule":{"type":"object","properties":{"kind":{"type":"string","const":"status"},"operator":{"type":"string","enum":["eq","neq","in"]},"value":{"anyOf":[{"type":"string","enum":["active","unsubscribed","bounced","complained","suppressed"]},{"type":"array","items":{"type":"string","enum":["active","unsubscribed","bounced","complained","suppressed"]}}]}},"required":["kind","operator","value"],"additionalProperties":false},"SegmentListRule":{"type":"object","properties":{"kind":{"type":"string","const":"list"},"list_id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$"},"operator":{"type":"string","enum":["in","not_in"]}},"required":["kind","list_id","operator"],"additionalProperties":false},"SegmentEventRule":{"type":"object","properties":{"kind":{"type":"string","const":"event"},"event_type":{"type":"string","enum":["sent","delivered","opened","clicked","bounced","complained","unsubscribed"]},"operator":{"type":"string","enum":["occurred","not_occurred"]},"within_days":{"type":"integer","minimum":1,"maximum":3650}},"required":["kind","event_type","operator"],"additionalProperties":false},"SegmentTrackingConsentRule":{"type":"object","properties":{"kind":{"type":"string","const":"tracking_consent"},"value":{"type":"boolean"}},"required":["kind","value"],"additionalProperties":false},"SegmentConsentRule":{"type":"object","properties":{"kind":{"type":"string","const":"consent"},"purpose":{"type":"string","pattern":"^[a-z][a-z0-9_]{2,40}$"},"status":{"type":"string","enum":["granted","refused","withdrawn","none"],"description":"`none`: no act recorded"}},"required":["kind","purpose","status"],"additionalProperties":false},"SegmentInactivityRule":{"type":"object","properties":{"kind":{"type":"string","const":"inactivity"},"operator":{"type":"string","enum":["is_inactive","is_active"]}},"required":["kind","operator"],"additionalProperties":false},"SegmentScoreRule":{"type":"object","properties":{"kind":{"type":"string","const":"score"},"operator":{"type":"string","enum":["gt","gte","lt","lte","between"]},"value":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"array","prefixItems":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}],"items":false,"minItems":2,"maxItems":2}]}},"required":["kind","operator","value"],"additionalProperties":false},"SegmentGroupRule":{"type":"object","properties":{"kind":{"type":"string","const":"group"},"op":{"type":"string","enum":["and","or"]},"rules":{"minItems":1,"maxItems":50,"type":"array","items":{"$ref":"#/components/schemas/SegmentRule"}}},"required":["kind","op","rules"],"additionalProperties":false},"SegmentRule":{"oneOf":[{"$ref":"#/components/schemas/SegmentGroupRule"},{"$ref":"#/components/schemas/SegmentAttributeRule"},{"$ref":"#/components/schemas/SegmentStatusRule"},{"$ref":"#/components/schemas/SegmentListRule"},{"$ref":"#/components/schemas/SegmentEventRule"},{"$ref":"#/components/schemas/SegmentTrackingConsentRule"},{"$ref":"#/components/schemas/SegmentConsentRule"},{"$ref":"#/components/schemas/SegmentInactivityRule"},{"$ref":"#/components/schemas/SegmentScoreRule"}]},"Problem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"detail":{"type":"string"},"code":{"type":"string"},"request_id":{"type":"string"},"errors":{}},"required":["type","title","status","code","request_id"],"additionalProperties":{},"description":"Error in RFC 9457 format (Problem Details)"},"Consent":{"type":"object","properties":{"granted":{"type":"boolean"},"at":{"type":["string","null"]},"source":{"type":["string","null"]}},"required":["granted","at","source"],"additionalProperties":false},"SequenceTrigger":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"list"},"list_id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"}},"required":["type","list_id"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"segment"},"segment_id":{"type":"string","pattern":"^seg_[0-9a-z]{26}$","example":"seg_0123456789abcdefghjkmnpqrs"}},"required":["type","segment_id"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"api"}},"required":["type"],"additionalProperties":false}]},"SequenceBranch":{"oneOf":[{"type":"object","properties":{"action":{"type":"string","const":"continue"}},"required":["action"],"additionalProperties":false},{"type":"object","properties":{"action":{"type":"string","const":"goto"},"step_id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["action","step_id"],"additionalProperties":false},{"type":"object","properties":{"action":{"type":"string","const":"exit"}},"required":["action"],"additionalProperties":false}]},"SendStep":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"type":{"type":"string","const":"send"},"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"next":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["id","type","template_id"],"additionalProperties":false},"WaitStep":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"type":{"type":"string","const":"wait"},"duration":{"type":"object","properties":{"value":{"type":"integer","exclusiveMinimum":0,"maximum":100000},"unit":{"type":"string","enum":["minutes","hours","days"]}},"required":["value","unit"],"additionalProperties":false},"business_days":{"type":"boolean"},"send_window":{"type":"object","properties":{"start":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},"end":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"}},"required":["start","end"],"additionalProperties":false},"next":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["id","type","duration"],"additionalProperties":false},"ConditionStep":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"type":{"type":"string","const":"condition"},"segment_id":{"type":"string","pattern":"^seg_[0-9a-z]{26}$","example":"seg_0123456789abcdefghjkmnpqrs"},"if_match":{"$ref":"#/components/schemas/SequenceBranch"},"else":{"$ref":"#/components/schemas/SequenceBranch"},"next":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["id","type","segment_id","if_match","else"],"additionalProperties":false},"WebhookStep":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"type":{"type":"string","const":"webhook"},"webhook_id":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"},"next":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["id","type","webhook_id"],"additionalProperties":false},"AbTestStep":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"type":{"type":"string","const":"ab_test"},"variants":{"minItems":2,"maxItems":5,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"weight":{"type":"integer","minimum":1,"maximum":100}},"required":["id","template_id","weight"],"additionalProperties":false}},"winner":{"type":"object","properties":{"metric":{"type":"string","enum":["opened","clicked","delivered"]},"evaluate_after":{"type":"object","properties":{"value":{"type":"integer","exclusiveMinimum":0,"maximum":1000},"unit":{"type":"string","enum":["hours","days"]}},"required":["value","unit"],"additionalProperties":false},"min_sample":{"type":"integer","minimum":10,"maximum":9007199254740991}},"required":["metric","evaluate_after","min_sample"],"additionalProperties":false},"winner_variant_id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"decided_at":{"type":"string"},"next":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["id","type","variants"],"additionalProperties":false},"SplitStep":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"type":{"type":"string","const":"split"},"branches":{"minItems":2,"maxItems":5,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"start":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["id","start"],"additionalProperties":false}},"join":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"},"next":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$"}},"required":["id","type","branches"],"additionalProperties":false},"SequenceStep":{"oneOf":[{"$ref":"#/components/schemas/SendStep"},{"$ref":"#/components/schemas/WaitStep"},{"$ref":"#/components/schemas/ConditionStep"},{"$ref":"#/components/schemas/WebhookStep"},{"$ref":"#/components/schemas/AbTestStep"},{"$ref":"#/components/schemas/SplitStep"}]},"ReenrollmentPolicy":{"oneOf":[{"type":"object","properties":{"policy":{"type":"string","const":"forbidden"}},"required":["policy"],"additionalProperties":false},{"type":"object","properties":{"policy":{"type":"string","const":"after_delay"},"delay_seconds":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["policy","delay_seconds"],"additionalProperties":false}]},"WebhookCreateRequest":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"format":"uri"},"events":{"minItems":1,"maxItems":7,"type":"array","items":{"type":"string","enum":["contact.unsubscribed","contact.bounced","contact.complained","enrollment.started","enrollment.completed","enrollment.exited","message.delivered"]}},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]}},"required":["url","events"],"additionalProperties":false},"WebhookPatchRequest":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"format":"uri"},"events":{"minItems":1,"maxItems":7,"type":"array","items":{"type":"string","enum":["contact.unsubscribed","contact.bounced","contact.complained","enrollment.started","enrollment.completed","enrollment.exited","message.delivered"]}},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"status":{"description":"Reactivates an automatically disabled webhook","type":"string","const":"active"}},"additionalProperties":false},"Webhook":{"type":"object","properties":{"id":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"description":{"type":["string","null"]},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"consecutive_failures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","url","events","description","status","disabled_reason","consecutive_failures","created_at","updated_at"],"additionalProperties":false},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string","pattern":"^wdl_[0-9a-z]{26}$","example":"wdl_0123456789abcdefghjkmnpqrs"},"webhook_id":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"},"event_type":{"type":"string"},"event_id":{"type":["string","null"]},"status":{"type":"string","enum":["pending","delivered","failed","exhausted"]},"attempts":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"last_status_code":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"last_error":{"type":["string","null"]},"next_attempt_at":{"type":["string","null"]},"delivered_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","webhook_id","event_type","event_id","status","attempts","last_status_code","last_error","next_attempt_at","delivered_at","created_at"],"additionalProperties":false},"ConsentActRequest":{"type":"object","properties":{"purpose":{"type":"string","pattern":"^[a-z][a-z0-9_]{2,40}$","description":"Purpose. Known: marketing_email, tracking_open_email, tracking_click_email, precontractual_contact, marketing_sms, marketing_whatsapp, marketing_push, transactional_sms, transactional_whatsapp; any other key is recorded with no effect."},"status":{"type":"string","enum":["granted","refused","withdrawn"]},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z","description":"Date of the act (ISO 8601). Each act has its own."},"source":{"type":"string","minLength":1,"maxLength":200,"description":"Source of the act (e.g. \"form:quote-request\", \"preference_center\")"},"proof_url":{"description":"Full URL of the proof (dated capture, archive…)","anyOf":[{"type":"string","maxLength":2000,"format":"uri"},{"type":"null"}]},"form_url":{"anyOf":[{"type":"string","maxLength":2000,"format":"uri"},{"type":"null"}]},"ip":{"description":"IP address of the person at the time of the act","anyOf":[{"type":"string","maxLength":45},{"type":"null"}]},"label":{"description":"Exact wording of the box ticked / notice read","anyOf":[{"type":"string","maxLength":1000},{"type":"null"}]},"list_id":{"description":"Target list (marketing purposes)","anyOf":[{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},{"type":"null"}]}},"required":["purpose","status","at","source"],"additionalProperties":false},"ConsentState":{"type":"object","properties":{"status":{"type":"string","enum":["granted","refused","withdrawn"]},"at":{"type":"string"},"source":{"type":"string"},"proof_url":{"type":["string","null"]},"label":{"type":["string","null"]},"list_id":{"type":["string","null"]},"first_granted_at":{"type":["string","null"]},"withdrawn_at":{"type":["string","null"]}},"required":["status","at","source","proof_url","label","list_id","first_granted_at","withdrawn_at"],"additionalProperties":false},"ConsentResult":{"type":"object","properties":{"purpose":{"type":"string"},"status":{"type":"string","enum":["granted","refused","withdrawn"]},"outcome":{"type":"string","enum":["applied","recorded_only","superseded","superseded_by_unsubscribe","contact_suppressed"]}},"required":["purpose","status","outcome"],"additionalProperties":false},"ConsentAct":{"type":"object","properties":{"id":{"type":"string","pattern":"^cns_[0-9a-z]{26}$","example":"cns_0123456789abcdefghjkmnpqrs"},"purpose":{"type":"string"},"status":{"type":"string","enum":["granted","refused","withdrawn"]},"occurred_at":{"type":"string"},"source":{"type":"string"},"proof_url":{"type":["string","null"]},"form_url":{"type":["string","null"]},"ip":{"type":["string","null"]},"label":{"type":["string","null"]},"list_id":{"type":["string","null"]},"outcome":{"type":"string"},"recorded_at":{"type":"string"}},"required":["id","purpose","status","occurred_at","source","proof_url","form_url","ip","label","list_id","outcome","recorded_at"],"additionalProperties":false},"Event":{"type":"object","properties":{"id":{"type":"string","pattern":"^evt_[0-9a-z]{26}$","example":"evt_0123456789abcdefghjkmnpqrs"},"type":{"type":"string"},"contact_id":{"type":["string","null"]},"message_id":{"type":["string","null"]},"sequence_id":{"type":["string","null"]},"step_id":{"type":["string","null"]},"list_id":{"type":["string","null"]},"template_id":{"type":["string","null"]},"enrollment_id":{"type":["string","null"]},"payload":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"occurred_at":{"type":"string"}},"required":["id","type","contact_id","message_id","sequence_id","step_id","list_id","template_id","enrollment_id","payload","occurred_at"],"additionalProperties":false},"TransactionalSendRequest":{"type":"object","properties":{"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs","description":"Template of type `transactional`"},"to":{"anyOf":[{"type":"object","properties":{"contact_id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"}},"required":["contact_id"],"additionalProperties":false},{"type":"object","properties":{"email":{},"first_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"last_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"attributes":{"type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{"type":["string","number","boolean"]}}},"required":["email"],"additionalProperties":false}],"description":"Recipient: an existing contact, or a free address (no contact created, address not persisted)"},"variables":{"description":"Rendering variable overrides (e.g. `order_id`, `reset_link`); `unsubscribe_url` is reserved","type":"object","propertyNames":{"type":"string","maxLength":100},"additionalProperties":{"type":"string","maxLength":4000}}},"required":["template_id","to"],"additionalProperties":false},"TrackingDomain":{"type":"object","properties":{"id":{"type":"string","pattern":"^trk_[0-9a-z]{26}$","example":"trk_0123456789abcdefghjkmnpqrs"},"domain":{"type":"string"},"status":{"type":"string","enum":["pending","verified","failed"]},"base_url":{"type":"string","description":"Base of the public URLs (pixels, clicks, unsubscribe) when the domain is verified"},"dns_records":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","const":"CNAME"},"name":{"type":"string"},"value":{"type":"string"}},"required":["type","name","value"],"additionalProperties":false}},"verified_at":{"type":["string","null"]},"last_checked_at":{"type":["string","null"]},"last_check_error":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","domain","status","base_url","dns_records","verified_at","last_checked_at","last_check_error","created_at"],"additionalProperties":false},"TenantQuotas":{"type":"object","properties":{"emails_per_day":{"type":"integer","minimum":0,"maximum":9007199254740991},"max_contacts":{"type":"integer","minimum":0,"maximum":9007199254740991},"api_calls_per_minute":{"type":"integer","minimum":1,"maximum":9007199254740991}},"required":["emails_per_day","max_contacts","api_calls_per_minute"],"additionalProperties":false},"TenantSettings":{"type":"object","properties":{"timezone":{"type":"string","minLength":1,"maxLength":64},"send_rate_per_second":{"type":"number","exclusiveMinimum":0},"soft_bounce_threshold":{"type":"integer","minimum":1,"maximum":9007199254740991},"allowed_reply_to":{"maxItems":50,"type":"array","items":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"bounce_rate_alert_threshold":{"type":"number","minimum":0,"maximum":1},"complaint_rate_alert_threshold":{"type":"number","minimum":0,"maximum":1},"inactivity":{"description":"F-STA-05: inactive contacts handling, based solely on `last_open_date` (F-STA-04)","anyOf":[{"type":"object","properties":{"after_days":{"type":"integer","minimum":30,"maximum":9007199254740991,"description":"No known open for N days (≥ 30)"},"min_sent":{"type":"integer","minimum":1,"maximum":9007199254740991,"description":"After at least N sends performed"},"action":{"type":"string","const":"exclude"}},"required":["after_days","min_sent","action"],"additionalProperties":false},{"type":"null"}]},"mta_outbound_ip":{"anyOf":[{"type":"string","maxLength":45},{"type":"null"}]},"retention":{"description":"NFR-RGPD-08: retention period overrides (days); absent = platform defaults","anyOf":[{"type":"object","properties":{"events_days":{"type":"integer","minimum":30,"maximum":9007199254740991},"audit_days":{"type":"integer","minimum":30,"maximum":9007199254740991},"webhook_deliveries_days":{"type":"integer","minimum":7,"maximum":9007199254740991}},"additionalProperties":false},{"type":"null"}]},"scoring":{"description":"F-SEG-04: lead scoring rules; absent/null = scoring disabled","anyOf":[{"$ref":"#/components/schemas/ScoringRules"},{"type":"null"}]}},"required":["timezone","send_rate_per_second","soft_bounce_threshold","allowed_reply_to","bounce_rate_alert_threshold","complaint_rate_alert_threshold"],"additionalProperties":false},"EffectiveRetention":{"type":"object","properties":{"events_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"audit_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"webhook_deliveries_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sandbox_captures_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"message_links_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["events_days","audit_days","webhook_deliveries_days","sandbox_captures_days","message_links_days"],"additionalProperties":false,"description":"Effective retention periods (defaults merged)"},"Tenant":{"type":"object","properties":{"id":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"status":{"type":"string","enum":["active","suspended","deleted"]},"quotas":{"$ref":"#/components/schemas/TenantQuotas"},"settings":{"$ref":"#/components/schemas/TenantSettings"},"sending_paused":{"type":"boolean"},"sending_paused_reason":{"type":["string","null"]},"slug":{"description":"Platform tracking subdomain `<slug>.<TRACKING_PLATFORM_SUFFIX>` (ADR-0007)","type":["string","null"]},"tracking_base_url":{"type":"string","description":"Base URL of the public links of upcoming sends (custom, platform or global)"},"tracking_base_kind":{"type":"string","enum":["custom","platform","global"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"deleted_at":{"type":["string","null"]}},"required":["id","name","status","quotas","settings","sending_paused","sending_paused_reason","slug","tracking_base_url","tracking_base_kind","created_at","updated_at","deleted_at"],"additionalProperties":false},"TenantUsage":{"type":"object","properties":{"emails_today":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"contacts_total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"api_keys_active":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["emails_today","contacts_total","api_keys_active"],"additionalProperties":false},"ApiKey":{"type":"object","properties":{"id":{"type":"string","pattern":"^key_[0-9a-z]{26}$","example":"key_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"prefix":{"type":"string"},"mode":{"type":"string","enum":["live","test"]},"scopes":{"type":"array","items":{"type":"string"}},"allowed_ips":{"type":"array","items":{"type":"string"},"description":"NFR-SEC-06: allowed IPs / CIDRs; empty = no restriction"},"status":{"type":"string","enum":["active","revoked"]},"last_used_at":{"type":["string","null"]},"created_at":{"type":"string"},"revoked_at":{"type":["string","null"]}},"required":["id","name","prefix","mode","scopes","allowed_ips","status","last_used_at","created_at","revoked_at"],"additionalProperties":false},"DnsRecord":{"type":"object","properties":{"type":{"type":"string","const":"TXT"},"name":{"type":"string"},"value":{"type":"string"},"purpose":{"type":"string","enum":["dkim","spf","dmarc"]},"note":{"type":"string"}},"required":["type","name","value","purpose"],"additionalProperties":false},"SendingDomain":{"type":"object","properties":{"id":{"type":"string","pattern":"^dom_[0-9a-z]{26}$","example":"dom_0123456789abcdefghjkmnpqrs"},"domain":{"type":"string"},"status":{"type":"string","enum":["pending","verified","failed"]},"dkim_selector":{"type":"string"},"spf_verified":{"type":"boolean"},"dkim_verified":{"type":"boolean"},"dmarc_verified":{"type":"boolean"},"last_checked_at":{"type":["string","null"]},"last_check_error":{"type":["string","null"]},"dns_records":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecord"}},"warmup":{"anyOf":[{"type":"object","properties":{"started_at":{"type":"string"},"day":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"daily_limit":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"null = plan complete, unlimited"},"sent_today":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["started_at","day","daily_limit","sent_today"],"additionalProperties":false},{"type":"null"}],"description":"F-SND-06: warm-up in progress (null otherwise)"},"created_at":{"type":"string"}},"required":["id","domain","status","dkim_selector","spf_verified","dkim_verified","dmarc_verified","last_checked_at","last_check_error","dns_records","warmup","created_at"],"additionalProperties":false},"AttributeDefinition":{"type":"object","properties":{"id":{"type":"string","pattern":"^atr_[0-9a-z]{26}$","example":"atr_0123456789abcdefghjkmnpqrs"},"key":{"type":"string"},"label":{"type":["string","null"]},"type":{"type":"string","enum":["text","number","boolean","date"]},"created_at":{"type":"string"}},"required":["id","key","label","type","created_at"],"additionalProperties":false},"AttributeDefinitionRequest":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$","description":"Key used in `attributes` and in segmentation (`attributes.<key>`)"},"type":{"type":"string","enum":["text","number","boolean","date"]},"label":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]}},"required":["key","type"],"additionalProperties":false},"AuditLog":{"type":"object","properties":{"id":{"type":"string","pattern":"^aud_[0-9a-z]{26}$","example":"aud_0123456789abcdefghjkmnpqrs"},"tenant_id":{"type":["string","null"]},"actor":{"type":"string","enum":["tenant","operator"]},"api_key_id":{"type":["string","null"]},"key_prefix":{"type":["string","null"]},"method":{"type":"string"},"path":{"type":"string"},"route":{"type":["string","null"]},"resource_id":{"type":["string","null"]},"status_code":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"request_id":{"type":"string"},"ip":{"type":["string","null"]},"occurred_at":{"type":"string"}},"required":["id","tenant_id","actor","api_key_id","key_prefix","method","path","route","resource_id","status_code","request_id","ip","occurred_at"],"additionalProperties":false},"CampaignAudience":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"list"},"list_id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"}},"required":["type","list_id"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"segment"},"segment_id":{"type":"string","pattern":"^seg_[0-9a-z]{26}$","example":"seg_0123456789abcdefghjkmnpqrs"}},"required":["type","segment_id"],"additionalProperties":false}]},"CampaignCreate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs","description":"Template of type `marketing`"},"audience":{"$ref":"#/components/schemas/CampaignAudience"},"scheduled_at":{"description":"Send date (UTC). Absent: immediate send on `POST …/schedule`","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"}},"required":["name","template_id","audience"],"additionalProperties":false},"CampaignPatch":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"audience":{"$ref":"#/components/schemas/CampaignAudience"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"},{"type":"null"}]}},"additionalProperties":false},"Campaign":{"type":"object","properties":{"id":{"type":"string","pattern":"^cmp_[0-9a-z]{26}$","example":"cmp_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"audience":{"$ref":"#/components/schemas/CampaignAudience"},"mode":{"type":"string","enum":["live","test"],"description":"Send mode inherited from the key that created the campaign: `test` = captured (Sandbox), never sent."},"status":{"type":"string","enum":["draft","scheduled","running","completed","cancelled","failed"]},"scheduled_at":{"type":["string","null"]},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"audience_count":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"queued_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"last_error":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","template_id","audience","mode","status","scheduled_at","started_at","completed_at","audience_count","queued_count","skipped_count","last_error","created_at","updated_at"],"additionalProperties":false},"CampaignDetail":{"type":"object","properties":{"id":{"type":"string","pattern":"^cmp_[0-9a-z]{26}$","example":"cmp_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"audience":{"$ref":"#/components/schemas/CampaignAudience"},"mode":{"type":"string","enum":["live","test"],"description":"Send mode inherited from the key that created the campaign: `test` = captured (Sandbox), never sent."},"status":{"type":"string","enum":["draft","scheduled","running","completed","cancelled","failed"]},"scheduled_at":{"type":["string","null"]},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"audience_count":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"queued_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"last_error":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"stats":{"type":"object","properties":{"sent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_hard":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_soft":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"complained":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unsubscribed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"performance":{"type":"object","properties":{"consented_population":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"opened":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"clicked":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"open_rate":{"type":["number","null"]},"click_rate":{"type":["number","null"]},"note":{"type":"string"}},"required":["consented_population","opened","clicked","open_rate","click_rate","note"],"additionalProperties":false}},"required":["sent","delivered","bounced_hard","bounced_soft","complained","unsubscribed","failed","performance"],"additionalProperties":false,"description":"Campaign aggregates since its creation (stats_daily)"}},"required":["id","name","template_id","audience","mode","status","scheduled_at","started_at","completed_at","audience_count","queued_count","skipped_count","last_error","created_at","updated_at","stats"],"additionalProperties":false},"TrackingConsent":{"type":"object","properties":{"granted":{"type":"boolean"},"at":{"type":["string","null"]},"source":{"type":["string","null"]},"withdrawn_at":{"type":["string","null"]}},"required":["granted","at","source","withdrawn_at"],"additionalProperties":false},"Contact":{"type":"object","properties":{"id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"email":{"type":"string"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"language":{"type":["string","null"]},"source":{"type":["string","null"]},"status":{"type":"string","enum":["active","unsubscribed","bounced","complained","suppressed"]},"attributes":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"consents":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/components/schemas/ConsentState"},"description":"Current state per consent purpose (ADR-0005)"},"optin_consent":{"description":"Derived from the `marketing_email` purpose","$ref":"#/components/schemas/Consent"},"tracking_consent":{"description":"Derived from the `tracking_open_email` purpose","$ref":"#/components/schemas/TrackingConsent"},"last_open_date":{"description":"Deliverability (F-STA-04): day of last open, overwritten","type":["string","null"]},"score":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Lead scoring (F-SEG-04): 0 when scoring is disabled"},"score_updated_at":{"type":["string","null"]},"unsubscribed_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","email","first_name","last_name","language","source","status","attributes","consents","optin_consent","tracking_consent","last_open_date","score","score_updated_at","unsubscribed_at","created_at","updated_at"],"additionalProperties":false},"ContactSubscription":{"type":"object","properties":{"list_id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"list_name":{"type":"string"},"status":{"type":"string","enum":["subscribed","unsubscribed"]},"source":{"type":["string","null"]},"subscribed_at":{"type":"string"},"unsubscribed_at":{"type":["string","null"]}},"required":["list_id","list_name","status","source","subscribed_at","unsubscribed_at"],"additionalProperties":false},"ContactEnrollmentSummary":{"type":"object","properties":{"id":{"type":"string","pattern":"^enr_[0-9a-z]{26}$","example":"enr_0123456789abcdefghjkmnpqrs"},"sequence_id":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"status":{"type":"string","enum":["active","completed","exited"]},"current_step_id":{"type":["string","null"]},"next_run_at":{"type":["string","null"]},"started_at":{"type":"string"},"ended_at":{"type":["string","null"]},"exit_reason":{"type":["string","null"]}},"required":["id","sequence_id","status","current_step_id","next_run_at","started_at","ended_at","exit_reason"],"additionalProperties":false},"ContactDetail":{"type":"object","properties":{"id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"email":{"type":"string"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"language":{"type":["string","null"]},"source":{"type":["string","null"]},"status":{"type":"string","enum":["active","unsubscribed","bounced","complained","suppressed"]},"attributes":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"consents":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/components/schemas/ConsentState"},"description":"Current state per consent purpose (ADR-0005)"},"optin_consent":{"description":"Derived from the `marketing_email` purpose","$ref":"#/components/schemas/Consent"},"tracking_consent":{"description":"Derived from the `tracking_open_email` purpose","$ref":"#/components/schemas/TrackingConsent"},"last_open_date":{"description":"Deliverability (F-STA-04): day of last open, overwritten","type":["string","null"]},"score":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Lead scoring (F-SEG-04): 0 when scoring is disabled"},"score_updated_at":{"type":["string","null"]},"unsubscribed_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"lists":{"type":"array","items":{"$ref":"#/components/schemas/ContactSubscription"}},"enrollments":{"type":"array","items":{"$ref":"#/components/schemas/ContactEnrollmentSummary"},"description":"Active enrollments"},"last_event":{"anyOf":[{"type":"object","properties":{"type":{"type":"string"},"occurred_at":{"type":"string"}},"required":["type","occurred_at"],"additionalProperties":false},{"type":"null"}]}},"required":["id","email","first_name","last_name","language","source","status","attributes","consents","optin_consent","tracking_consent","last_open_date","score","score_updated_at","unsubscribed_at","created_at","updated_at","lists","enrollments","last_event"],"additionalProperties":false},"ContactUpsertRequest":{"type":"object","properties":{"email":{"type":"string","minLength":3,"maxLength":320},"first_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"last_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"language":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}]},"source":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"attributes":{"description":"Custom attributes; `null` removes","type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{}},"consents":{"maxItems":20,"type":"array","items":{"$ref":"#/components/schemas/ConsentActRequest"},"description":"Consent acts: at most one per purpose and per call"},"optin_consent":{"description":"Deprecated: equivalent to a `marketing_email` act","type":"object","properties":{"granted":{"type":"boolean"},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z","description":"Proof timestamp"},"source":{"type":"string","minLength":1,"maxLength":200,"description":"Proof source (e.g. \"form:landing-2026-09\", \"import:attestation\")"}},"required":["granted","at","source"],"additionalProperties":false},"tracking_consent":{"description":"Deprecated: equivalent to a `tracking_open_email` act","type":"object","properties":{"granted":{"type":"boolean"},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z","description":"Proof timestamp"},"source":{"type":"string","minLength":1,"maxLength":200,"description":"Proof source (e.g. \"form:landing-2026-09\", \"import:attestation\")"}},"required":["granted","at","source"],"additionalProperties":false},"subscriptions":{"description":"Subscriptions to perform in the same call","maxItems":20,"type":"array","items":{"type":"object","properties":{"list_id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"source":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]}},"required":["list_id"],"additionalProperties":false}}},"required":["email"],"additionalProperties":false},"ContactPatchRequest":{"type":"object","properties":{"first_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"last_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"language":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}]},"source":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"attributes":{"description":"Custom attributes; `null` removes","type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{}},"consents":{"maxItems":20,"type":"array","items":{"$ref":"#/components/schemas/ConsentActRequest"},"description":"Consent acts: at most one per purpose and per call"},"optin_consent":{"description":"Deprecated: equivalent to a `marketing_email` act","type":"object","properties":{"granted":{"type":"boolean"},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z","description":"Proof timestamp"},"source":{"type":"string","minLength":1,"maxLength":200,"description":"Proof source (e.g. \"form:landing-2026-09\", \"import:attestation\")"}},"required":["granted","at","source"],"additionalProperties":false},"tracking_consent":{"description":"Deprecated: equivalent to a `tracking_open_email` act","type":"object","properties":{"granted":{"type":"boolean"},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z","description":"Proof timestamp"},"source":{"type":"string","minLength":1,"maxLength":200,"description":"Proof source (e.g. \"form:landing-2026-09\", \"import:attestation\")"}},"required":["granted","at","source"],"additionalProperties":false}},"additionalProperties":false},"EnrollmentStepLog":{"type":"object","properties":{"step_id":{"type":"string"},"step_type":{"type":"string"},"outcome":{"type":"string"},"detail":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"occurred_at":{"type":"string"}},"required":["step_id","step_type","outcome","detail","occurred_at"],"additionalProperties":false},"Enrollment":{"type":"object","properties":{"id":{"type":"string","pattern":"^enr_[0-9a-z]{26}$","example":"enr_0123456789abcdefghjkmnpqrs"},"sequence_id":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"sequence_version":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"contact_id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"status":{"type":"string","enum":["active","completed","exited"]},"current_step_id":{"type":["string","null"]},"next_run_at":{"description":"Next due time (wait step), ISO 8601 UTC","type":["string","null"]},"trigger":{"type":"object","properties":{"type":{"type":"string","enum":["list","segment","api","branch"]},"ref":{"type":["string","null"]}},"required":["type","ref"],"additionalProperties":false},"parent_enrollment_id":{"anyOf":[{"type":"string","pattern":"^enr_[0-9a-z]{26}$","example":"enr_0123456789abcdefghjkmnpqrs"},{"type":"null"}]},"branch_path":{"type":["string","null"]},"exit_reason":{"type":["string","null"]},"started_at":{"type":"string"},"ended_at":{"type":["string","null"]},"history":{"type":"array","items":{"$ref":"#/components/schemas/EnrollmentStepLog"}},"children":{"description":"Parallel branches of this main enrollment","type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^enr_[0-9a-z]{26}$","example":"enr_0123456789abcdefghjkmnpqrs"},"branch_path":{"type":["string","null"]},"status":{"type":"string","enum":["active","completed","exited"]},"current_step_id":{"type":["string","null"]},"exit_reason":{"type":["string","null"]}},"required":["id","branch_path","status","current_step_id","exit_reason"],"additionalProperties":false}}},"required":["id","sequence_id","sequence_version","contact_id","status","current_step_id","next_run_at","trigger","parent_enrollment_id","branch_path","exit_reason","started_at","ended_at"],"additionalProperties":false},"ExportParams":{"type":"object","properties":{"from":{"description":"Period start (UTC day, inclusive) — on-demand export","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"description":"Period end (UTC day, inclusive) — on-demand export","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"sequence_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"}},"list_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"}},"types":{"description":"Event types (kind `events`)","maxItems":30,"type":"array","items":{"type":"string","minLength":1,"maxLength":60}},"bom":{"description":"CSV: prefix with a UTF-8 BOM (Excel)","type":"boolean"}},"additionalProperties":false},"ExportDelivery":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"download"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"webhook"},"webhook_id":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"}},"required":["type","webhook_id"],"additionalProperties":false}]},"ExportScheduleCreateRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["stats_overview","stats_sequences","stats_lists","events"]},"format":{"default":"json","type":"string","enum":["json","csv"]},"params":{"default":{},"type":"object","properties":{"sequence_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"}},"list_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"}},"types":{"description":"Event types (kind `events`)","maxItems":30,"type":"array","items":{"type":"string","minLength":1,"maxLength":60}},"bom":{"description":"CSV: prefix with a UTF-8 BOM (Excel)","type":"boolean"}},"additionalProperties":false},"frequency":{"type":"string","enum":["daily","weekly","monthly"]},"hour_utc":{"default":6,"type":"integer","minimum":0,"maximum":23},"day_of":{"default":1,"description":"Weekly: 1 (Monday) to 7 (Sunday); monthly: day of month 1 to 28","type":"integer","minimum":1,"maximum":28},"delivery":{"default":{"type":"download"},"$ref":"#/components/schemas/ExportDelivery"}},"required":["name","kind","format","params","frequency","hour_utc","day_of","delivery"],"additionalProperties":false},"ExportSchedulePatchRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"format":{"type":"string","enum":["json","csv"]},"params":{"type":"object","properties":{"sequence_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"}},"list_ids":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"}},"types":{"description":"Event types (kind `events`)","maxItems":30,"type":"array","items":{"type":"string","minLength":1,"maxLength":60}},"bom":{"description":"CSV: prefix with a UTF-8 BOM (Excel)","type":"boolean"}},"additionalProperties":false},"frequency":{"type":"string","enum":["daily","weekly","monthly"]},"hour_utc":{"type":"integer","minimum":0,"maximum":23},"day_of":{"type":"integer","minimum":1,"maximum":28},"delivery":{"$ref":"#/components/schemas/ExportDelivery"},"status":{"type":"string","enum":["active","paused"]}},"additionalProperties":false},"ExportCreateRequest":{"type":"object","properties":{"kind":{"type":"string","enum":["stats_overview","stats_sequences","stats_lists","events"]},"format":{"default":"json","type":"string","enum":["json","csv"]},"params":{"default":{},"$ref":"#/components/schemas/ExportParams"},"delivery":{"default":{"type":"download"},"$ref":"#/components/schemas/ExportDelivery"}},"required":["kind","format","params","delivery"],"additionalProperties":false},"ExportSchedule":{"type":"object","properties":{"id":{"type":"string","pattern":"^exs_[0-9a-z]{26}$","example":"exs_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"kind":{"type":"string","enum":["stats_overview","stats_sequences","stats_lists","events"]},"format":{"type":"string","enum":["json","csv"]},"params":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"frequency":{"type":"string","enum":["daily","weekly","monthly"]},"hour_utc":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"day_of":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivery":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"status":{"type":"string","enum":["active","paused"]},"next_run_at":{"type":["string","null"]},"last_run_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","kind","format","params","frequency","hour_utc","day_of","delivery","status","next_run_at","last_run_at","created_at","updated_at"],"additionalProperties":false},"Export":{"type":"object","properties":{"id":{"type":"string","pattern":"^exp_[0-9a-z]{26}$","example":"exp_0123456789abcdefghjkmnpqrs"},"schedule_id":{"type":["string","null"]},"kind":{"type":"string","enum":["stats_overview","stats_sequences","stats_lists","events"]},"format":{"type":"string","enum":["json","csv"]},"params":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"period":{"anyOf":[{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to"],"additionalProperties":false},{"type":"null"}]},"status":{"type":"string","enum":["pending","running","completed","failed"]},"row_count":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"size_bytes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"sha256":{"type":["string","null"]},"error":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"download_url":{"description":"Present when the export is ready and not expired","type":["string","null"]},"created_at":{"type":"string"},"completed_at":{"type":["string","null"]}},"required":["id","schedule_id","kind","format","params","period","status","row_count","size_bytes","sha256","error","expires_at","download_url","created_at","completed_at"],"additionalProperties":false},"ImportAttestation":{"type":"object","properties":{"attested_by":{"type":"string","minLength":1,"maxLength":200,"description":"Person or system attesting (e.g. \"dpo@tenant.com\")"},"statement":{"type":"string","minLength":20,"maxLength":2000,"description":"Statement of lawfulness of the base (consents collected, transitional regime closed, …)"},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z","description":"Attestation timestamp"}},"required":["attested_by","statement","at"],"additionalProperties":false},"ImportReportLine":{"type":"object","properties":{"line":{"type":"integer","minimum":1,"maximum":9007199254740991},"status":{"type":"string","enum":["created","updated","failed"]},"code":{"type":"string"},"detail":{"type":"string"}},"required":["line","status"],"additionalProperties":false},"ContactImport":{"type":"object","properties":{"id":{"type":"string"},"job_id":{"type":"string"},"status":{"type":"string","enum":["pending","running","completed","failed"]},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"processed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"created":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"updated":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"attestation":{"$ref":"#/components/schemas/ImportAttestation"},"report":{"type":"array","items":{"$ref":"#/components/schemas/ImportReportLine"},"description":"One entry per processed row; never an e-mail address"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","job_id","status","total","processed","created","updated","failed","attestation","report","created_at","updated_at"],"additionalProperties":false},"ContactImportRequest":{"type":"object","properties":{"attestation":{"description":"Mandatory (NFR-RGPD-06): timestamped attestation of the lawfulness of the imported base","$ref":"#/components/schemas/ImportAttestation"},"default_source":{"description":"Source applied to rows without `source`","type":"string","maxLength":200},"rows":{"minItems":1,"type":"array","items":{},"description":"Rows in ContactUpsertRequest format (max 10000)"}},"required":["rows"],"additionalProperties":false},"Job":{"type":"object","properties":{"id":{"type":"string","pattern":"^job_[0-9a-z]{26}$","example":"job_0123456789abcdefghjkmnpqrs"},"type":{"type":"string"},"status":{"type":"string","enum":["pending","running","completed","failed"]},"progress":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"result":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"error":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","type","status","progress","result","error","created_at","updated_at"],"additionalProperties":false},"List":{"type":"object","properties":{"id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"description":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","description","created_at","updated_at"],"additionalProperties":false},"ListDetail":{"type":"object","properties":{"id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"description":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"subscribers_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","description","created_at","updated_at","subscribers_count"],"additionalProperties":false},"ListRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]}},"required":["name"],"additionalProperties":false},"ListSubscription":{"type":"object","properties":{"list_id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"contact_id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"status":{"type":"string","enum":["subscribed","unsubscribed"]},"source":{"type":["string","null"]},"subscribed_at":{"type":"string"},"unsubscribed_at":{"type":["string","null"]}},"required":["list_id","contact_id","status","source","subscribed_at","unsubscribed_at"],"additionalProperties":false},"ListSubscribeRequest":{"type":"object","properties":{"contact_id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"email":{"type":"string","minLength":3,"maxLength":320},"source":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]}},"additionalProperties":false},"Message":{"type":"object","properties":{"id":{"type":"string","pattern":"^msg_[0-9a-z]{26}$","example":"msg_0123456789abcdefghjkmnpqrs"},"kind":{"type":"string","enum":["sequence","test","campaign","transactional"]},"mode":{"type":"string","enum":["live","test"]},"status":{"type":"string"},"contact_id":{"type":["string","null"]},"template_id":{"type":["string","null"]},"sequence_id":{"type":["string","null"]},"campaign_id":{"type":["string","null"]},"subject":{"type":["string","null"]},"attempts":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"last_error":{"type":["string","null"]},"queued_at":{"type":"string"},"sent_at":{"type":["string","null"]},"delivered_at":{"type":["string","null"]},"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^evt_[0-9a-z]{26}$","example":"evt_0123456789abcdefghjkmnpqrs"},"type":{"type":"string"},"occurred_at":{"type":"string"},"payload":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["id","type","occurred_at","payload"],"additionalProperties":false}}},"required":["id","kind","mode","status","contact_id","template_id","sequence_id","campaign_id","subject","attempts","last_error","queued_at","sent_at","delivered_at","events"],"additionalProperties":false},"GenericProviderWebhook":{"type":"object","properties":{"events":{"minItems":1,"maxItems":1000,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":200},"type":{"type":"string","enum":["delivered","bounce_hard","bounce_soft","complaint"]},"provider_message_id":{"type":"string","minLength":1,"maxLength":500},"occurred_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"reason":{"type":"string","maxLength":1000}},"required":["id","type","provider_message_id","occurred_at"],"additionalProperties":false}}},"required":["events"],"additionalProperties":false},"SandboxMessageSummary":{"type":"object","properties":{"id":{"type":"string"},"message_id":{"type":"string"},"contact_id":{"type":["string","null"]},"to":{"type":"string"},"from":{"type":"string"},"reply_to":{"type":["string","null"]},"subject":{"type":"string"},"created_at":{"type":"string"}},"required":["id","message_id","contact_id","to","from","reply_to","subject","created_at"],"additionalProperties":false},"SandboxMessage":{"type":"object","properties":{"id":{"type":"string"},"message_id":{"type":"string"},"contact_id":{"type":["string","null"]},"to":{"type":"string"},"from":{"type":"string"},"reply_to":{"type":["string","null"]},"subject":{"type":"string"},"created_at":{"type":"string"},"html":{"type":"string"},"text":{"type":["string","null"]},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["id","message_id","contact_id","to","from","reply_to","subject","created_at","html","text","headers"],"additionalProperties":false},"Segment":{"type":"object","properties":{"id":{"type":"string","pattern":"^seg_[0-9a-z]{26}$","example":"seg_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"description":{"type":["string","null"]},"rules":{},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","description","rules","created_at","updated_at"],"additionalProperties":false},"SegmentMember":{"type":"object","properties":{"id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"email":{"type":"string"},"status":{"type":"string"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","email","status","first_name","last_name","created_at"],"additionalProperties":false},"SegmentPreviewRequest":{"type":"object","properties":{"rules":{"$ref":"#/components/schemas/SegmentRule"},"limit":{"default":10,"type":"integer","minimum":1,"maximum":50}},"required":["rules","limit"],"additionalProperties":false},"SegmentPreview":{"type":"object","properties":{"total_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sample":{"type":"array","items":{"$ref":"#/components/schemas/SegmentMember"}}},"required":["total_count","sample"],"additionalProperties":false},"Sequence":{"type":"object","properties":{"id":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["draft","active","paused","archived"]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"trigger":{"$ref":"#/components/schemas/SequenceTrigger"},"steps":{"minItems":1,"maxItems":100,"type":"array","items":{"$ref":"#/components/schemas/SequenceStep"}},"reenrollment":{"$ref":"#/components/schemas/ReenrollmentPolicy"},"exit_on_trigger_segment_exit":{"type":"boolean"},"required_consent_purpose":{"type":"string","pattern":"^[a-z][a-z0-9_]{2,40}$","description":"Consent purpose the contact must have granted to be enrolled and receive the e-mails (`marketing_email` by default, e.g. `precontractual_contact`). A tenant-wide unsubscribe blocks regardless."},"counts":{"type":"object","properties":{"active":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"completed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"exited":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["active","completed","exited"],"additionalProperties":false,"description":"Main enrollments per status; always returned, including by the list endpoint."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","description","status","version","trigger","steps","reenrollment","exit_on_trigger_segment_exit","required_consent_purpose","counts","created_at","updated_at"],"additionalProperties":false},"SequenceCreate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"trigger":{"$ref":"#/components/schemas/SequenceTrigger"},"steps":{"minItems":1,"maxItems":100,"type":"array","items":{"$ref":"#/components/schemas/SequenceStep"}},"reenrollment":{"default":{"policy":"forbidden"},"$ref":"#/components/schemas/ReenrollmentPolicy"},"exit_on_trigger_segment_exit":{"default":false,"type":"boolean"},"required_consent_purpose":{"default":"marketing_email","type":"string","pattern":"^[a-z][a-z0-9_]{2,40}$","description":"Consent purpose the contact must have granted to be enrolled and receive the e-mails (`marketing_email` by default, e.g. `precontractual_contact`). A tenant-wide unsubscribe blocks regardless."}},"required":["name","trigger","steps","reenrollment","exit_on_trigger_segment_exit","required_consent_purpose"],"additionalProperties":false},"SequencePatch":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"trigger":{"$ref":"#/components/schemas/SequenceTrigger"},"steps":{"minItems":1,"maxItems":100,"type":"array","items":{"$ref":"#/components/schemas/SequenceStep"}},"reenrollment":{"$ref":"#/components/schemas/ReenrollmentPolicy"},"exit_on_trigger_segment_exit":{"type":"boolean"},"required_consent_purpose":{"type":"string","pattern":"^[a-z][a-z0-9_]{2,40}$","description":"Consent purpose the contact must have granted to be enrolled and receive the e-mails (`marketing_email` by default, e.g. `precontractual_contact`). A tenant-wide unsubscribe blocks regardless."},"migrate_active_enrollments":{"default":false,"type":"boolean"}},"required":["migrate_active_enrollments"],"additionalProperties":false},"EnrollmentCreate":{"type":"object","properties":{"contact_id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"}},"required":["contact_id"],"additionalProperties":false},"PerformanceStats":{"type":"object","properties":{"consented_population":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"opened":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"clicked":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"open_rate":{"type":["number","null"]},"click_rate":{"type":["number","null"]},"note":{"type":"string"}},"required":["consented_population","opened","clicked","open_rate","click_rate","note"],"additionalProperties":false},"Aggregate":{"type":"object","properties":{"sent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_hard":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_soft":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"complained":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unsubscribed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"performance":{"$ref":"#/components/schemas/PerformanceStats"}},"required":["sent","delivered","bounced_hard","bounced_soft","complained","unsubscribed","failed","performance"],"additionalProperties":false},"Suppression":{"type":"object","properties":{"id":{"type":"string","pattern":"^sup_[0-9a-z]{26}$","example":"sup_0123456789abcdefghjkmnpqrs"},"email":{"description":"NULL after GDPR erasure (only the fingerprint remains)","type":["string","null"]},"email_hash":{"type":"string"},"reason":{"type":"string","enum":["unsubscribed","hard_bounce","complaint","manual","erased"]},"detail":{"type":["string","null"]},"source":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","email","email_hash","reason","detail","source","created_at"],"additionalProperties":false},"TemplateTracking":{"type":"object","properties":{"deliverability_pixel":{"default":true,"description":"Deliverability pixel (exempt from consent, NFR-RGPD-02)","type":"boolean"},"performance_pixel":{"default":true,"description":"Performance pixel (inserted only with a valid tracking consent)","type":"boolean"},"click_tracking":{"default":false,"description":"Link rewriting to measure clicks (F-TPL-05): applied only if the contact’s `tracking_click_email` purpose is granted (NFR-RGPD-04)","type":"boolean"}},"required":["deliverability_pixel","performance_pixel","click_tracking"],"additionalProperties":false},"TemplateCreate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"subject":{"type":"string","minLength":1,"maxLength":998},"html_body":{"type":"string","minLength":1,"description":"Must contain {{unsubscribe_url}} (F-TPL-03)"},"text_body":{"anyOf":[{"type":"string","maxLength":200000},{"type":"null"}]},"from_email":{},"from_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"reply_to":{"anyOf":[{},{"type":"null"}]},"variable_defaults":{"default":{},"type":"object","propertyNames":{"type":"string","maxLength":100},"additionalProperties":{"type":"string","maxLength":2000}},"tracking":{"default":{"deliverability_pixel":true,"performance_pixel":true,"click_tracking":false},"$ref":"#/components/schemas/TemplateTracking"},"kind":{"default":"marketing","type":"string","enum":["marketing","transactional"],"description":"`marketing`: series and campaigns, unsubscribe link mandatory, pixels according to consent. `transactional`: single service e-mail (`POST /v1/messages`), no unsubscribe link required, no performance pixel nor click tracking."}},"required":["name","subject","html_body","from_email","variable_defaults","tracking","kind"],"additionalProperties":false},"TemplatePatch":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"subject":{"type":"string","minLength":1,"maxLength":998},"html_body":{"type":"string","minLength":1},"text_body":{"anyOf":[{"type":"string","maxLength":200000},{"type":"null"}]},"from_email":{},"from_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"reply_to":{"anyOf":[{},{"type":"null"}]},"variable_defaults":{"type":"object","propertyNames":{"type":"string","maxLength":100},"additionalProperties":{"type":"string","maxLength":2000}},"tracking":{"$ref":"#/components/schemas/TemplateTracking"}},"additionalProperties":false},"Template":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"subject":{"type":"string"},"html_body":{"type":"string"},"text_body":{"type":["string","null"]},"from_email":{"type":"string"},"from_name":{"type":["string","null"]},"reply_to":{"type":["string","null"]},"variable_defaults":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"tracking":{"type":"object","properties":{"deliverability_pixel":{"type":"boolean"},"performance_pixel":{"type":"boolean"},"click_tracking":{"type":"boolean"}},"required":["deliverability_pixel","performance_pixel","click_tracking"],"additionalProperties":false},"kind":{"type":"string","enum":["marketing","transactional"],"description":"`marketing`: series and campaigns, unsubscribe link mandatory, pixels according to consent. `transactional`: single service e-mail (`POST /v1/messages`), no unsubscribe link required, no performance pixel nor click tracking."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","subject","html_body","text_body","from_email","from_name","reply_to","variable_defaults","tracking","kind","created_at","updated_at"],"additionalProperties":false},"FictiveContact":{"type":"object","properties":{"email":{},"first_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"last_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"language":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}]},"source":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"attributes":{"default":{},"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":["string","number","boolean","null"]}},"tracking_consent":{"default":false,"description":"Simulates a valid tracking consent","type":"boolean"},"click_consent":{"default":false,"description":"Simulates the `tracking_click_email` purpose as granted","type":"boolean"}},"required":["email","attributes","tracking_consent","click_consent"],"additionalProperties":false},"TemplateRenderRequest":{"type":"object","properties":{"contact_id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"contact":{"$ref":"#/components/schemas/FictiveContact"}},"additionalProperties":false},"TemplateRenderResult":{"type":"object","properties":{"subject":{"type":"string"},"html":{"type":"string"},"text":{"type":["string","null"]},"warnings":{"type":"array","items":{"type":"string"}},"tracking":{"type":"object","properties":{"deliverability_pixel":{"type":"boolean"},"performance_pixel":{"type":"boolean"},"click_tracking":{"type":"boolean","description":"Click tracking would apply to a real send to this contact"}},"required":["deliverability_pixel","performance_pixel","click_tracking"],"additionalProperties":false},"tracking_consented":{"type":"boolean"},"click_tracking_applied":{"type":"boolean","const":false,"description":"In preview, links are never rewritten (no message, no database write)"}},"required":["subject","html","text","warnings","tracking","tracking_consented","click_tracking_applied"],"additionalProperties":false},"ContactExport":{"type":"object","properties":{"exported_at":{"type":"string"},"contact":{"$ref":"#/components/schemas/Contact"},"subscriptions":{"type":"array","items":{"$ref":"#/components/schemas/ContactSubscription"}},"enrollments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^enr_[0-9a-z]{26}$","example":"enr_0123456789abcdefghjkmnpqrs"},"sequence_id":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"status":{"type":"string","enum":["active","completed","exited"]},"current_step_id":{"type":["string","null"]},"next_run_at":{"type":["string","null"]},"started_at":{"type":"string"},"ended_at":{"type":["string","null"]},"exit_reason":{"type":["string","null"]},"sequence_version_id":{"type":"string","pattern":"^sqv_[0-9a-z]{26}$","example":"sqv_0123456789abcdefghjkmnpqrs"},"trigger_type":{"type":"string"},"step_logs":{"type":"array","items":{"type":"object","properties":{"step_id":{"type":"string"},"step_type":{"type":"string"},"outcome":{"type":"string"},"detail":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"occurred_at":{"type":"string"}},"required":["step_id","step_type","outcome","detail","occurred_at"],"additionalProperties":false}}},"required":["id","sequence_id","status","current_step_id","next_run_at","started_at","ended_at","exit_reason","sequence_version_id","trigger_type","step_logs"],"additionalProperties":false}},"consent_acts":{"type":"array","items":{"$ref":"#/components/schemas/ConsentAct"}},"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^evt_[0-9a-z]{26}$","example":"evt_0123456789abcdefghjkmnpqrs"},"type":{"type":"string"},"occurred_at":{"type":"string"},"message_id":{"type":["string","null"]},"sequence_id":{"type":["string","null"]},"list_id":{"type":["string","null"]},"payload":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["id","type","occurred_at","message_id","sequence_id","list_id","payload"],"additionalProperties":false}}},"required":["exported_at","contact","subscriptions","enrollments","consent_acts","events"],"additionalProperties":false},"SuppressionRequest":{"type":"object","properties":{"email":{"type":"string","minLength":3,"maxLength":320},"reason":{"type":"string","minLength":1,"maxLength":500},"source":{"type":"string","maxLength":200}},"required":["email","reason"],"additionalProperties":false},"RetentionPurgeSummary":{"type":"object","properties":{"tenants":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"totals":{"type":"object","properties":{"events":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"audit_logs":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"webhook_deliveries":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sandbox_captures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"message_links":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["events","audit_logs","webhook_deliveries","sandbox_captures","message_links"],"additionalProperties":false},"global":{"type":"object","properties":{"idempotency_keys":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"operator_audit_logs":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["idempotency_keys","operator_audit_logs"],"additionalProperties":false},"started_at":{"type":"string"},"finished_at":{"type":"string"}},"required":["tenants","totals","global","started_at","finished_at"],"additionalProperties":false},"TrackingDomainCreateRequest":{"type":"object","properties":{"domain":{"type":"string","minLength":3,"maxLength":253}},"required":["domain"],"additionalProperties":false},"MtaStatus":{"type":"object","properties":{"enabled":{"type":"boolean"},"smarthost":{"type":["string","null"]},"tls":{"type":"string","enum":["opportunistic","require"]},"mta_sts":{"type":"boolean"},"outbound_ips":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"helo":{"type":"string"}},"required":["address","helo"],"additionalProperties":false}},"local_addresses":{"type":"array","items":{"type":"string"}},"pool":{"type":"object","properties":{"enabled":{"type":"boolean"},"connections":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"total":{"type":"number"},"idle":{"type":"number"},"busy":{"type":"number"},"waiting":{"type":"number"}},"required":["key","total","idle","busy","waiting"],"additionalProperties":false}}},"required":["enabled","connections"],"additionalProperties":false},"deferred":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"until":{"type":["string","null"]},"ttl_seconds":{"type":["number","null"]}},"required":["key","until","ttl_seconds"],"additionalProperties":false}},"rates":{"type":"array","items":{"type":"object","properties":{"provider":{"type":"string"},"ip":{"type":"string"},"minute":{"type":"string"},"count":{"type":"number"},"limit":{"type":["number","null"]}},"required":["provider","ip","minute","count","limit"],"additionalProperties":false}},"limits":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"ips":{"description":"Outbound IPs: per-IP warm-up and provider families for which the IP is degraded (ADR-0008)","type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"helo":{"type":"string"},"warmup":{"anyOf":[{"type":"object","properties":{"started_at":{"type":"string"},"day":{"type":"number"},"daily_limit":{"type":["number","null"]},"sent_today":{"type":"number"}},"required":["started_at","day","daily_limit","sent_today"],"additionalProperties":false},{"type":"null"}]},"health":{"type":"object","properties":{"degraded_for":{"type":"array","items":{"type":"string"}}},"required":["degraded_for"],"additionalProperties":false}},"required":["address","helo","warmup","health"],"additionalProperties":false}},"selfcheck":{"description":"DNS self-check (PTR, FCrDNS, bounce domain MX, SPF), cached 10 min","anyOf":[{"type":"object","properties":{"checked_at":{"type":"string"},"results":{"type":"array","items":{"type":"object","properties":{"check":{"type":"string"},"ok":{"type":"boolean"},"detail":{"type":"string"}},"required":["check","ok","detail"],"additionalProperties":false}}},"required":["checked_at","results"],"additionalProperties":false},{"type":"null"}]}},"required":["enabled"],"additionalProperties":false},"TemplateTestSendRequest":{"type":"object","properties":{"to":{},"contact_id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"}},"required":["to"],"additionalProperties":false},"SandboxEventRequest":{"type":"object","properties":{"message_id":{"type":"string","pattern":"^msg_[0-9a-z]{26}$","example":"msg_0123456789abcdefghjkmnpqrs"},"type":{"type":"string","enum":["delivered","bounce_hard","bounce_soft","complaint"]},"reason":{"type":"string","maxLength":500}},"required":["message_id","type"],"additionalProperties":false},"AbTestDecision":{"type":"object","properties":{"variant_id":{"type":"string","minLength":1,"maxLength":40}},"required":["variant_id"],"additionalProperties":false}}},"paths":{"/health":{"get":{"summary":"Liveness","tags":["System"],"security":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]}},"required":["status"],"additionalProperties":false}}}}}}},"/health/ready":{"get":{"summary":"Readiness (database, redis, queues)","tags":["System"],"description":"`not_ready` (503) when the database or Redis is unavailable; `degraded` (503) when a queue exceeds `READINESS_MAX_WAITING` waiting jobs (optional threshold, to enable only with an orchestrator that does not restart the API on this signal).","security":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ready","degraded","not_ready"]},"checks":{"type":"object","properties":{"database":{"type":"boolean"},"redis":{"type":"boolean"},"queues":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","properties":{"waiting":{"type":"number"},"active":{"type":"number"},"delayed":{"type":"number"},"failed":{"type":"number"}},"required":["waiting","active","delayed","failed"],"additionalProperties":false}}},"required":["database","redis","queues"],"additionalProperties":false}},"required":["status","checks"],"additionalProperties":false}}}},"503":{"description":"Service Unavailable — dependency down or platform not ready","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ready","degraded","not_ready"]},"checks":{"type":"object","properties":{"database":{"type":"boolean"},"redis":{"type":"boolean"},"queues":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","properties":{"waiting":{"type":"number"},"active":{"type":"number"},"delayed":{"type":"number"},"failed":{"type":"number"}},"required":["waiting","active","delayed","failed"],"additionalProperties":false}}},"required":["database","redis","queues"],"additionalProperties":false}},"required":["status","checks"],"additionalProperties":false}}}}}}},"/v1/contacts":{"put":{"operationId":"upsertContact","summary":"Upsert a contact by e-mail (F-CON-01), with optional subscriptions","tags":["Contacts"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactUpsertRequestInput"}}}},"x-required-scope":"contacts:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"email":{"type":"string"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"language":{"type":["string","null"]},"source":{"type":["string","null"]},"status":{"type":"string","enum":["active","unsubscribed","bounced","complained","suppressed"]},"attributes":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"consents":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/components/schemas/ConsentState"},"description":"Current state per consent purpose (ADR-0005)"},"optin_consent":{"$ref":"#/components/schemas/Consent"},"tracking_consent":{"$ref":"#/components/schemas/TrackingConsent"},"last_open_date":{"description":"Deliverability (F-STA-04): day of last open, overwritten","type":["string","null"]},"score":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Lead scoring (F-SEG-04): 0 when scoring is disabled"},"score_updated_at":{"type":["string","null"]},"unsubscribed_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"created":{"type":"boolean","enum":[false]},"consent_results":{"type":"array","items":{"$ref":"#/components/schemas/ConsentResult"},"description":"Outcome of each consent act sent in the request"}},"required":["id","email","first_name","last_name","language","source","status","attributes","consents","optin_consent","tracking_consent","last_open_date","score","score_updated_at","unsubscribed_at","created_at","updated_at","created","consent_results"],"additionalProperties":false}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"email":{"type":"string"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"language":{"type":["string","null"]},"source":{"type":["string","null"]},"status":{"type":"string","enum":["active","unsubscribed","bounced","complained","suppressed"]},"attributes":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"consents":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/components/schemas/ConsentState"},"description":"Current state per consent purpose (ADR-0005)"},"optin_consent":{"$ref":"#/components/schemas/Consent"},"tracking_consent":{"$ref":"#/components/schemas/TrackingConsent"},"last_open_date":{"description":"Deliverability (F-STA-04): day of last open, overwritten","type":["string","null"]},"score":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Lead scoring (F-SEG-04): 0 when scoring is disabled"},"score_updated_at":{"type":["string","null"]},"unsubscribed_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"created":{"type":"boolean","enum":[true]},"consent_results":{"type":"array","items":{"$ref":"#/components/schemas/ConsentResult"},"description":"Outcome of each consent act sent in the request"}},"required":["id","email","first_name","last_name","language","source","status","attributes","consents","optin_consent","tracking_consent","last_open_date","score","score_updated_at","unsubscribed_at","created_at","updated_at","created","consent_results"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"listContacts","summary":"Paginated contact search (F-CON-05)","tags":["Contacts"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string"},"in":"query","name":"email","required":false},{"schema":{"type":"string","enum":["active","unsubscribed","bounced","complained","suppressed"]},"in":"query","name":"status","required":false},{"schema":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"in":"query","name":"list_id","required":false},{"schema":{"type":"string","pattern":"^seg_[0-9a-z]{26}$","example":"seg_0123456789abcdefghjkmnpqrs"},"in":"query","name":"segment_id","required":false},{"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"},"in":"query","name":"created_after","required":false},{"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"},"in":"query","name":"created_before","required":false},{"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"in":"query","name":"score_gte","required":false},{"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"in":"query","name":"score_lte","required":false}],"x-required-scope":"contacts:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Contact"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/contacts/{id}":{"get":{"operationId":"getContact","summary":"Full contact record (F-CON-05, F-STA-03)","tags":["Contacts"],"parameters":[{"schema":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"contacts:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactDetail"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"operationId":"patchContact","summary":"Partial update of a contact","tags":["Contacts"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactPatchRequestInput"}}}},"parameters":[{"schema":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"contacts:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"email":{"type":"string"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"language":{"type":["string","null"]},"source":{"type":["string","null"]},"status":{"type":"string","enum":["active","unsubscribed","bounced","complained","suppressed"]},"attributes":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"consents":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/components/schemas/ConsentState"},"description":"Current state per consent purpose (ADR-0005)"},"optin_consent":{"$ref":"#/components/schemas/Consent"},"tracking_consent":{"$ref":"#/components/schemas/TrackingConsent"},"last_open_date":{"description":"Deliverability (F-STA-04): day of last open, overwritten","type":["string","null"]},"score":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Lead scoring (F-SEG-04): 0 when scoring is disabled"},"score_updated_at":{"type":["string","null"]},"unsubscribed_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"consent_results":{"type":"array","items":{"$ref":"#/components/schemas/ConsentResult"},"description":"Outcome of each consent act sent in the request"}},"required":["id","email","first_name","last_name","language","source","status","attributes","consents","optin_consent","tracking_consent","last_open_date","score","score_updated_at","unsubscribed_at","created_at","updated_at","consent_results"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"operationId":"deleteContact","summary":"GDPR erasure (F-CON-06): purge + fingerprint on the suppression list","tags":["Contacts"],"parameters":[{"schema":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"contacts:write","responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/contacts/{id}/consents":{"get":{"operationId":"listContactConsents","summary":"Register of a contact’s consent acts (proofs, NFR-RGPD-05)","tags":["Contacts"],"parameters":[{"schema":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"contacts:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ConsentAct"}}},"required":["data"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"recordContactConsents","summary":"Record consent acts (granted, refused, withdrawn) per purpose","tags":["Contacts"],"description":"One act per purpose and per call. A refusal is recorded with no effect; a `marketing_email` withdrawal unsubscribes immediately; a `marketing_email` grant dated before the unsubscribe does not reactivate.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"consents":{"minItems":1,"maxItems":20,"type":"array","items":{"$ref":"#/components/schemas/ConsentActRequestInput"},"description":"Consent acts: at most one per purpose and per call"}},"required":["consents"]}}}},"parameters":[{"schema":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"contacts:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"email":{"type":"string"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"language":{"type":["string","null"]},"source":{"type":["string","null"]},"status":{"type":"string","enum":["active","unsubscribed","bounced","complained","suppressed"]},"attributes":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"consents":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/components/schemas/ConsentState"},"description":"Current state per consent purpose (ADR-0005)"},"optin_consent":{"$ref":"#/components/schemas/Consent"},"tracking_consent":{"$ref":"#/components/schemas/TrackingConsent"},"last_open_date":{"description":"Deliverability (F-STA-04): day of last open, overwritten","type":["string","null"]},"score":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Lead scoring (F-SEG-04): 0 when scoring is disabled"},"score_updated_at":{"type":["string","null"]},"unsubscribed_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"consent_results":{"type":"array","items":{"$ref":"#/components/schemas/ConsentResult"},"description":"Outcome of each consent act sent in the request"}},"required":["id","email","first_name","last_name","language","source","status","attributes","consents","optin_consent","tracking_consent","last_open_date","score","score_updated_at","unsubscribed_at","created_at","updated_at","consent_results"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/contacts/{id}/unsubscribe":{"post":{"operationId":"unsubscribeContact","summary":"Tenant-wide unsubscribe of a contact (F-LST-02)","tags":["Contacts"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"string","minLength":1,"maxLength":200}},"required":["source"]}}}},"parameters":[{"schema":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"contacts:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contact"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/contacts/{id}/score":{"post":{"operationId":"adjustContactScore","summary":"Manual lead scoring adjustment (F-SEG-04)","tags":["Contacts"],"description":"Applies a delta to the score (bounded by the tenant rules) and logs `score.updated`. 409 `scoring_disabled` when no rules are set.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"delta":{"type":"integer","minimum":-1000,"maximum":1000},"reason":{"type":"string","minLength":1,"maxLength":200}},"required":["delta","reason"]}}}},"parameters":[{"schema":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"contacts:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contact"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/contacts/{id}/score/recompute":{"post":{"operationId":"recomputeContactScore","summary":"Full score recomputation from the last 365 days of the event log","tags":["Contacts"],"parameters":[{"schema":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"contacts:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contact"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/contacts/{id}/export":{"get":{"operationId":"exportContact","summary":"Right of access / portability export (F-CON-07)","tags":["Contacts"],"parameters":[{"schema":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"contacts:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactExport"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/contacts/imports":{"post":{"operationId":"createContactImport","summary":"Asynchronous batch import of contacts (F-CON-08)","tags":["Contacts"],"description":"Each row has the shape of a single upsert. Processing is asynchronous (`GET /v1/jobs/{job_id}`, `GET /v1/contacts/imports/{import_id}` for the row-by-row report). NFR-RGPD-06 rule: a row without a `tracking_open_email` act is imported without non-exempt tracking; a row without `marketing_email` is imported without opt-in (no send until a consent is proven). Rows are purged from the database when processing ends; the report contains no e-mail address.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportRequestInput"}}}},"x-required-scope":"contacts:write","responses":{"202":{"description":"Accepted — processed asynchronously","content":{"application/json":{"schema":{"type":"object","properties":{"job_id":{"type":"string","pattern":"^job_[0-9a-z]{26}$","example":"job_0123456789abcdefghjkmnpqrs"},"import_id":{"type":"string","pattern":"^imp_[0-9a-z]{26}$","example":"imp_0123456789abcdefghjkmnpqrs"},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["job_id","import_id","total"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Payload Too Large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/contacts/imports/{id}":{"get":{"operationId":"getContactImport","summary":"State and row-by-row report of an import","tags":["Contacts"],"parameters":[{"schema":{"type":"string","pattern":"^imp_[0-9a-z]{26}$","example":"imp_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"contacts:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImport"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/contacts/{id}/activity":{"get":{"operationId":"getContactActivity","summary":"Activity feed of a contact (F-CON-09)","tags":["Contacts"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"minItems":1,"type":"array","items":{"type":"string","minLength":1,"maxLength":64}},"in":"query","name":"type","required":false,"description":"Event types, comma-separated"},{"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"},"in":"query","name":"occurred_after","required":false},{"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"},"in":"query","name":"occurred_before","required":false},{"schema":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"contacts:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attributes":{"post":{"operationId":"createAttributeDefinition","summary":"Declare a typed custom attribute (F-CON-02)","tags":["Contacts"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttributeDefinitionRequestInput"}}}},"x-required-scope":"contacts:write","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttributeDefinition"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"listAttributeDefinitions","summary":"List the tenant’s custom attributes","tags":["Contacts"],"x-required-scope":"contacts:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AttributeDefinition"}}},"required":["data"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attributes/{id}":{"delete":{"operationId":"deleteAttributeDefinition","summary":"Delete an attribute definition (existing values are no longer validated nor segmentable)","tags":["Contacts"],"parameters":[{"schema":{"type":"string","pattern":"^atr_[0-9a-z]{26}$","example":"atr_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"contacts:write","responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/lists":{"post":{"operationId":"createList","summary":"Create a list","tags":["Lists"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRequestInput"}}}},"x-required-scope":"lists:write","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/List"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"listLists","summary":"List lists","tags":["Lists"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false}],"x-required-scope":"lists:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/List"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/lists/{id}":{"get":{"operationId":"getList","summary":"List detail (with subscriber count)","tags":["Lists"],"parameters":[{"schema":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"lists:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDetail"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"operationId":"patchList","summary":"Update a list","tags":["Lists"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]}}}}}},"parameters":[{"schema":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"lists:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/List"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"operationId":"deleteList","summary":"Delete a list (refused if it triggers an active sequence)","tags":["Lists"],"parameters":[{"schema":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"lists:write","responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/lists/{id}/subscriptions":{"post":{"operationId":"subscribeToList","summary":"Subscribe a contact to a list (source + timestamp) — idempotent","tags":["Lists"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSubscribeRequestInput"}}}},"parameters":[{"schema":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"lists:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSubscription"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSubscription"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/lists/{id}/subscriptions/{contact_id}":{"delete":{"operationId":"unsubscribeFromList","summary":"Unsubscribe a contact from a list (F-LST-02)","tags":["Lists"],"parameters":[{"schema":{"type":"string","maxLength":200},"in":"query","name":"source","required":false},{"schema":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true},{"schema":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"in":"path","name":"contact_id","required":true}],"x-required-scope":"lists:write","responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/suppressions":{"get":{"operationId":"listSuppressions","summary":"Read the tenant suppression list","tags":["Suppressions"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","enum":["unsubscribed","hard_bounce","complaint","manual","erased"]},"in":"query","name":"reason","required":false},{"schema":{"type":"string"},"in":"query","name":"email","required":false}],"x-required-scope":"suppressions:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Suppression"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"addSuppression","summary":"Add an address to the suppression list (reason required)","tags":["Suppressions"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionRequestInput"}}}},"x-required-scope":"suppressions:write","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Suppression"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/suppressions/{id}":{"delete":{"operationId":"removeSuppression","summary":"Remove an entry from the suppression list (id `sup_…` or SHA-256 fingerprint) — reason required","tags":["Suppressions"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500}}},{"type":"null"}]}}}},"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":500},"in":"query","name":"reason","required":false},{"schema":{"type":"string","minLength":1,"maxLength":80},"in":"path","name":"id","required":true}],"x-required-scope":"suppressions:write","responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/segments/preview":{"post":{"operationId":"previewSegment","summary":"Preview a segment without creating it (F-SEG-03): count + sample","tags":["Segments"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentPreviewRequestInput"}}}},"x-required-scope":"segments:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentPreview"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/segments":{"post":{"operationId":"createSegment","summary":"Create a dynamic segment","tags":["Segments"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"rules":{"$ref":"#/components/schemas/SegmentRuleInput"}},"required":["name","rules"]}}}},"x-required-scope":"segments:write","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Segment"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"listSegments","summary":"List segments","tags":["Segments"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false}],"x-required-scope":"segments:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Segment"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/segments/{id}":{"get":{"operationId":"getSegment","summary":"Segment detail","tags":["Segments"],"parameters":[{"schema":{"type":"string","pattern":"^seg_[0-9a-z]{26}$","example":"seg_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"segments:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Segment"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"operationId":"updateSegment","summary":"Update a segment","tags":["Segments"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"rules":{"$ref":"#/components/schemas/SegmentRuleInput"}}}}}},"parameters":[{"schema":{"type":"string","pattern":"^seg_[0-9a-z]{26}$","example":"seg_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"segments:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Segment"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"operationId":"deleteSegment","summary":"Delete a segment (refused if a non-archived sequence uses it)","tags":["Segments"],"parameters":[{"schema":{"type":"string","pattern":"^seg_[0-9a-z]{26}$","example":"seg_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"segments:write","responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/segments/{id}/members":{"get":{"operationId":"listSegmentMembers","summary":"Current members of a segment (paginated) with on-demand count","tags":["Segments"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","pattern":"^seg_[0-9a-z]{26}$","example":"seg_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"segments:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SegmentMember"}},"next_cursor":{"type":["string","null"]},"total_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["data","next_cursor","total_count"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/events":{"get":{"operationId":"listEvents","summary":"Filterable event log (type, contact, sequence, message, list, period)","tags":["Events & Stats"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"minItems":1,"type":"array","items":{"type":"string","enum":["contact.created","contact.updated","contact.deleted","list.subscribed","list.unsubscribed","enrollment.started","enrollment.completed","enrollment.exited","queued","sent","delivered","bounced","complained","unsubscribed","opened","clicked","deferred","send_failed","suppressed","consent.recorded","webhook.disabled","import.completed","ab_test.decided","campaign.started","campaign.completed"]}},"in":"query","name":"type","required":false,"description":"One or more types, comma-separated"},{"schema":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"in":"query","name":"contact_id","required":false},{"schema":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"in":"query","name":"sequence_id","required":false},{"schema":{"type":"string","pattern":"^msg_[0-9a-z]{26}$","example":"msg_0123456789abcdefghjkmnpqrs"},"in":"query","name":"message_id","required":false},{"schema":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"in":"query","name":"list_id","required":false},{"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"},"in":"query","name":"occurred_after","required":false},{"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"},"in":"query","name":"occurred_before","required":false}],"x-required-scope":"events:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/stats/sequences/{id}":{"get":{"operationId":"getSequenceStats","summary":"Sequence aggregates over a period (option group_by=step|day|variant)","tags":["Events & Stats"],"parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"in":"query","name":"from","required":false},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"in":"query","name":"to","required":false},{"schema":{"type":"string","enum":["step","day","variant"]},"in":"query","name":"group_by","required":false},{"schema":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"stats:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"sequence_id":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"period":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["from","to"],"additionalProperties":false},"totals":{"$ref":"#/components/schemas/Aggregate"},"by_step":{"type":"array","items":{"type":"object","properties":{"sent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_hard":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_soft":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"complained":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unsubscribed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"performance":{"$ref":"#/components/schemas/PerformanceStats"},"step_id":{"type":"string"},"template_id":{"type":["string","null"]}},"required":["sent","delivered","bounced_hard","bounced_soft","complained","unsubscribed","failed","performance","step_id","template_id"],"additionalProperties":false}},"by_day":{"type":"array","items":{"type":"object","properties":{"sent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_hard":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_soft":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"complained":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unsubscribed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"performance":{"$ref":"#/components/schemas/PerformanceStats"},"day":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["sent","delivered","bounced_hard","bounced_soft","complained","unsubscribed","failed","performance","day"],"additionalProperties":false}},"by_variant":{"description":"F-SEQ-08: per-variant aggregates of ab_test steps","type":"array","items":{"type":"object","properties":{"sent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_hard":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_soft":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"complained":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unsubscribed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"performance":{"$ref":"#/components/schemas/PerformanceStats"},"step_id":{"type":"string"},"variant_id":{"type":"string"}},"required":["sent","delivered","bounced_hard","bounced_soft","complained","unsubscribed","failed","performance","step_id","variant_id"],"additionalProperties":false}}},"required":["sequence_id","period","totals"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/stats/lists/{id}":{"get":{"operationId":"getListStats","summary":"List aggregates over a period","tags":["Events & Stats"],"parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"in":"query","name":"from","required":false},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"in":"query","name":"to","required":false},{"schema":{"type":"string","enum":["day"]},"in":"query","name":"group_by","required":false},{"schema":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"stats:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"list_id":{"type":"string","pattern":"^lst_[0-9a-z]{26}$","example":"lst_0123456789abcdefghjkmnpqrs"},"period":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["from","to"],"additionalProperties":false},"totals":{"$ref":"#/components/schemas/Aggregate"},"by_day":{"type":"array","items":{"type":"object","properties":{"sent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_hard":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_soft":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"complained":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unsubscribed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"performance":{"$ref":"#/components/schemas/PerformanceStats"},"day":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["sent","delivered","bounced_hard","bounced_soft","complained","unsubscribed","failed","performance","day"],"additionalProperties":false}}},"required":["list_id","period","totals"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/stats/campaigns/{id}":{"get":{"operationId":"getCampaignStats","summary":"One-shot campaign aggregates over a period (P2)","tags":["Events & Stats"],"parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"in":"query","name":"from","required":false},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"in":"query","name":"to","required":false},{"schema":{"type":"string","enum":["day"]},"in":"query","name":"group_by","required":false},{"schema":{"type":"string","pattern":"^cmp_[0-9a-z]{26}$","example":"cmp_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"stats:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"campaign_id":{"type":"string","pattern":"^cmp_[0-9a-z]{26}$","example":"cmp_0123456789abcdefghjkmnpqrs"},"period":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["from","to"],"additionalProperties":false},"totals":{"$ref":"#/components/schemas/Aggregate"},"by_day":{"type":"array","items":{"type":"object","properties":{"sent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_hard":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_soft":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"complained":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unsubscribed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"performance":{"$ref":"#/components/schemas/PerformanceStats"},"day":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["sent","delivered","bounced_hard","bounced_soft","complained","unsubscribed","failed","performance","day"],"additionalProperties":false}}},"required":["campaign_id","period","totals"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/stats/templates/{id}":{"get":{"operationId":"getTemplateStats","summary":"Template aggregates over a period (all uses: series, campaigns, transactional)","tags":["Events & Stats"],"parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"in":"query","name":"from","required":false},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"in":"query","name":"to","required":false},{"schema":{"type":"string","enum":["day"]},"in":"query","name":"group_by","required":false},{"schema":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"stats:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"period":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["from","to"],"additionalProperties":false},"totals":{"$ref":"#/components/schemas/Aggregate"},"by_day":{"type":"array","items":{"type":"object","properties":{"sent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_hard":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_soft":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"complained":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unsubscribed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"performance":{"$ref":"#/components/schemas/PerformanceStats"},"day":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["sent","delivered","bounced_hard","bounced_soft","complained","unsubscribed","failed","performance","day"],"additionalProperties":false}}},"required":["template_id","period","totals"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/stats/overview":{"get":{"operationId":"getOverviewStats","summary":"Tenant aggregates over a period","tags":["Events & Stats"],"parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"in":"query","name":"from","required":false},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"in":"query","name":"to","required":false},{"schema":{"type":"string","enum":["day"]},"in":"query","name":"group_by","required":false}],"x-required-scope":"stats:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"period":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["from","to"],"additionalProperties":false},"totals":{"$ref":"#/components/schemas/Aggregate"},"by_day":{"type":"array","items":{"type":"object","properties":{"sent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_hard":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_soft":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"complained":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unsubscribed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"performance":{"$ref":"#/components/schemas/PerformanceStats"},"day":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["sent","delivered","bounced_hard","bounced_soft","complained","unsubscribed","failed","performance","day"],"additionalProperties":false}}},"required":["period","totals"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/jobs/{id}":{"get":{"operationId":"getJob","summary":"Track an asynchronous operation","tags":["Jobs"],"parameters":[{"schema":{"type":"string","pattern":"^job_[0-9a-z]{26}$","example":"job_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/tenants":{"post":{"operationId":"adminCreateTenant","summary":"Create a tenant","tags":["Admin"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"quotas":{"type":"object","properties":{"emails_per_day":{"type":"integer","minimum":0,"maximum":9007199254740991},"max_contacts":{"type":"integer","minimum":0,"maximum":9007199254740991},"api_calls_per_minute":{"type":"integer","minimum":1,"maximum":9007199254740991}}},"settings":{"type":"object","properties":{"timezone":{"type":"string","minLength":1,"maxLength":64},"send_rate_per_second":{"type":"number","exclusiveMinimum":0},"soft_bounce_threshold":{"type":"integer","minimum":1,"maximum":9007199254740991},"allowed_reply_to":{"maxItems":50,"type":"array","items":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"bounce_rate_alert_threshold":{"type":"number","minimum":0,"maximum":1},"complaint_rate_alert_threshold":{"type":"number","minimum":0,"maximum":1},"inactivity":{"description":"F-STA-05: inactive contacts handling, based solely on `last_open_date` (F-STA-04)","anyOf":[{"type":"object","properties":{"after_days":{"type":"integer","minimum":30,"maximum":9007199254740991,"description":"No known open for N days (≥ 30)"},"min_sent":{"type":"integer","minimum":1,"maximum":9007199254740991,"description":"After at least N sends performed"},"action":{"type":"string","enum":["exclude"]}},"required":["after_days","min_sent","action"]},{"type":"null"}]},"mta_outbound_ip":{"anyOf":[{"type":"string","maxLength":45},{"type":"null"}]},"retention":{"description":"NFR-RGPD-08: retention period overrides (days); absent = platform defaults","anyOf":[{"type":"object","properties":{"events_days":{"type":"integer","minimum":30,"maximum":9007199254740991},"audit_days":{"type":"integer","minimum":30,"maximum":9007199254740991},"webhook_deliveries_days":{"type":"integer","minimum":7,"maximum":9007199254740991}}},{"type":"null"}]},"scoring":{"description":"F-SEG-04: lead scoring rules; absent/null = scoring disabled","anyOf":[{"$ref":"#/components/schemas/ScoringRulesInput"},{"type":"null"}]}}},"slug":{"description":"Platform tracking subdomain; derived from the name when absent","type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{1,30}[a-z0-9])?$"}},"required":["name"]}}}},"x-operator-only":true,"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tenant"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"adminListTenants","summary":"List tenants","tags":["Admin"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","enum":["active","suspended","deleted"]},"in":"query","name":"status","required":false}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Tenant"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/tenants/{id}":{"get":{"operationId":"adminGetTenant","summary":"Tenant detail, quotas and usage","tags":["Admin"],"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"status":{"type":"string","enum":["active","suspended","deleted"]},"quotas":{"$ref":"#/components/schemas/TenantQuotas"},"settings":{"$ref":"#/components/schemas/TenantSettings"},"sending_paused":{"type":"boolean"},"sending_paused_reason":{"type":["string","null"]},"slug":{"description":"Platform tracking subdomain `<slug>.<TRACKING_PLATFORM_SUFFIX>` (ADR-0007)","type":["string","null"]},"tracking_base_url":{"type":"string","description":"Base URL of the public links of upcoming sends (custom, platform or global)"},"tracking_base_kind":{"type":"string","enum":["custom","platform","global"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"deleted_at":{"type":["string","null"]},"usage":{"$ref":"#/components/schemas/TenantUsage"},"retention":{"$ref":"#/components/schemas/EffectiveRetention"}},"required":["id","name","status","quotas","settings","sending_paused","sending_paused_reason","slug","tracking_base_url","tracking_base_kind","created_at","updated_at","deleted_at","usage","retention"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"operationId":"adminUpdateTenant","summary":"Update a tenant (name, quotas, settings, suspension, sending pause)","tags":["Admin"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"quotas":{"type":"object","properties":{"emails_per_day":{"type":"integer","minimum":0,"maximum":9007199254740991},"max_contacts":{"type":"integer","minimum":0,"maximum":9007199254740991},"api_calls_per_minute":{"type":"integer","minimum":1,"maximum":9007199254740991}}},"settings":{"type":"object","properties":{"timezone":{"type":"string","minLength":1,"maxLength":64},"send_rate_per_second":{"type":"number","exclusiveMinimum":0},"soft_bounce_threshold":{"type":"integer","minimum":1,"maximum":9007199254740991},"allowed_reply_to":{"maxItems":50,"type":"array","items":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"bounce_rate_alert_threshold":{"type":"number","minimum":0,"maximum":1},"complaint_rate_alert_threshold":{"type":"number","minimum":0,"maximum":1},"inactivity":{"description":"F-STA-05: inactive contacts handling, based solely on `last_open_date` (F-STA-04)","anyOf":[{"type":"object","properties":{"after_days":{"type":"integer","minimum":30,"maximum":9007199254740991,"description":"No known open for N days (≥ 30)"},"min_sent":{"type":"integer","minimum":1,"maximum":9007199254740991,"description":"After at least N sends performed"},"action":{"type":"string","enum":["exclude"]}},"required":["after_days","min_sent","action"]},{"type":"null"}]},"mta_outbound_ip":{"anyOf":[{"type":"string","maxLength":45},{"type":"null"}]},"retention":{"description":"NFR-RGPD-08: retention period overrides (days); absent = platform defaults","anyOf":[{"type":"object","properties":{"events_days":{"type":"integer","minimum":30,"maximum":9007199254740991},"audit_days":{"type":"integer","minimum":30,"maximum":9007199254740991},"webhook_deliveries_days":{"type":"integer","minimum":7,"maximum":9007199254740991}}},{"type":"null"}]},"scoring":{"description":"F-SEG-04: lead scoring rules; absent/null = scoring disabled","anyOf":[{"$ref":"#/components/schemas/ScoringRulesInput"},{"type":"null"}]}}},"status":{"type":"string","enum":["active","suspended"]},"sending_paused":{"type":"boolean"},"slug":{"description":"Platform tracking subdomain; `null` to remove it","anyOf":[{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{1,30}[a-z0-9])?$"},{"type":"null"}]}}}}}},"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tenant"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"operationId":"adminDeleteTenant","summary":"Delete a tenant (status deleted + revocation of all its keys; no physical purge in V1)","tags":["Admin"],"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-operator-only":true,"responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/retention/purge":{"post":{"operationId":"adminRunRetentionPurge","summary":"Run the retention purge (NFR-RGPD-08) immediately on all tenants","tags":["Admin"],"description":"Deletes events, audit logs, webhook deliveries, sandbox captures and rewritten links beyond the retention periods (platform defaults or the tenant’s `settings.retention`). Consent proofs, aggregates and messages are never purged.","x-operator-only":true,"responses":{"202":{"description":"Accepted — processed asynchronously","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionPurgeSummary"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/tenants/{id}/scoring/defaults":{"post":{"operationId":"applyDefaultScoringRules","summary":"Apply the default lead scoring rule set to the tenant (F-SEG-04)","tags":["Admin"],"description":"opened +5, clicked +10, delivered +1, list.subscribed +10, consent.granted +5, bounced_soft −5, unsubscribed −50, complained −100; decay 1/day; bounds 0–100.","parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"scoring":{"$ref":"#/components/schemas/ScoringRules"}},"required":["scoring"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/tenants/{id}/api-keys":{"post":{"operationId":"adminCreateApiKey","summary":"Create an API key for a tenant (the clear-text value is returned only once)","tags":["Admin"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"mode":{"type":"string","enum":["live","test"]},"scopes":{"minItems":1,"type":"array","items":{"type":"string","enum":["contacts:read","contacts:write","lists:read","lists:write","segments:read","segments:write","sequences:read","sequences:write","templates:read","templates:write","events:read","stats:read","suppressions:read","suppressions:write","webhooks:read","webhooks:write","audit:read","campaigns:read","campaigns:write","messages:write","exports:read","exports:write"]}},"allowed_ips":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":64}}},"required":["name","mode","scopes"]}}}},"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-operator-only":true,"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^key_[0-9a-z]{26}$","example":"key_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"prefix":{"type":"string"},"mode":{"type":"string","enum":["live","test"]},"scopes":{"type":"array","items":{"type":"string"}},"allowed_ips":{"type":"array","items":{"type":"string"},"description":"NFR-SEC-06: allowed IPs / CIDRs; empty = no restriction"},"status":{"type":"string","enum":["active","revoked"]},"last_used_at":{"type":["string","null"]},"created_at":{"type":"string"},"revoked_at":{"type":["string","null"]},"key":{"type":"string"}},"required":["id","name","prefix","mode","scopes","allowed_ips","status","last_used_at","created_at","revoked_at","key"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"adminListApiKeys","summary":"List a tenant’s API keys","tags":["Admin"],"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}}},"required":["data"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/tenants/{id}/api-keys/{key_id}":{"patch":{"operationId":"adminPatchApiKey","summary":"Update an API key (name, allowed IPs — NFR-SEC-06)","tags":["Admin"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"allowed_ips":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":64}}}}}}},"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true},{"schema":{"type":"string","pattern":"^key_[0-9a-z]{26}$","example":"key_0123456789abcdefghjkmnpqrs"},"in":"path","name":"key_id","required":true}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKey"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"operationId":"adminRevokeApiKey","summary":"Revoke an API key","tags":["Admin"],"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true},{"schema":{"type":"string","pattern":"^key_[0-9a-z]{26}$","example":"key_0123456789abcdefghjkmnpqrs"},"in":"path","name":"key_id","required":true}],"x-operator-only":true,"responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/tenants/{id}/tracking-domains":{"post":{"operationId":"adminCreateTrackingDomain","summary":"Declare a tracking domain (pixels, clicks, unsubscribe) — returns the CNAME to publish","tags":["Admin"],"description":"The domain must point via CNAME to the platform target (`TRACKING_CNAME_TARGET`). TLS termination is handled by the reverse proxy. A domain can belong to only one tenant.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackingDomainCreateRequestInput"}}}},"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-operator-only":true,"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackingDomain"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"adminListTrackingDomains","summary":"List a tenant’s tracking domains","tags":["Admin"],"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TrackingDomain"}}},"required":["data"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/tenants/{id}/tracking-domains/{domain_id}/verify":{"post":{"operationId":"adminVerifyTrackingDomain","summary":"Verify the CNAME of a tracking domain","tags":["Admin"],"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true},{"schema":{"type":"string","pattern":"^trk_[0-9a-z]{26}$","example":"trk_0123456789abcdefghjkmnpqrs"},"in":"path","name":"domain_id","required":true}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackingDomain"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/tenants/{id}/tracking-domains/{domain_id}":{"delete":{"operationId":"adminDeleteTrackingDomain","summary":"Remove a tracking domain (upcoming sends fall back to the global base URL)","tags":["Admin"],"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true},{"schema":{"type":"string","pattern":"^trk_[0-9a-z]{26}$","example":"trk_0123456789abcdefghjkmnpqrs"},"in":"path","name":"domain_id","required":true}],"x-operator-only":true,"responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/tenants/{id}/sending-domains":{"post":{"operationId":"adminCreateSendingDomain","summary":"Declare a sending domain (returns the SPF/DKIM/DMARC DNS records to publish)","tags":["Admin"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string","minLength":3,"maxLength":253}},"required":["domain"]}}}},"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-operator-only":true,"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendingDomain"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"adminListSendingDomains","summary":"List a tenant’s sending domains","tags":["Admin"],"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SendingDomain"}}},"required":["data"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/tenants/{id}/sending-domains/{domain_id}/verify":{"post":{"operationId":"adminVerifySendingDomain","summary":"Verify the DNS records (SPF, DKIM, DMARC) of a sending domain","tags":["Admin"],"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true},{"schema":{"type":"string","pattern":"^dom_[0-9a-z]{26}$","example":"dom_0123456789abcdefghjkmnpqrs"},"in":"path","name":"domain_id","required":true}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendingDomain"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/tenants/{id}/sending-domains/{domain_id}/warmup":{"post":{"operationId":"adminSendingDomainWarmup","summary":"Start or stop the warm-up of a sending domain (F-SND-06)","tags":["Admin"],"description":"Daily e-mail cap growing since the start. Default plan: 50, 100, 200, 400, 800, 1500, 3000, 6000, 10000, 20000 then unlimited. Beyond the cap, sends are deferred to the next day (`deferred`, reason `warmup_limit`).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["start","stop"]},"plan":{"description":"Custom daily caps (day 1 → N)","minItems":1,"maxItems":60,"type":"array","items":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}}},"required":["action"]}}}},"parameters":[{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true},{"schema":{"type":"string","pattern":"^dom_[0-9a-z]{26}$","example":"dom_0123456789abcdefghjkmnpqrs"},"in":"path","name":"domain_id","required":true}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendingDomain"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/mta/status":{"get":{"operationId":"adminMtaStatus","summary":"Built-in MTA diagnostics (connection pool, deferred domains, rates, outbound IPs)","tags":["Admin"],"description":"Answers `{ enabled: false }` when the live provider is not the built-in MTA (`MAIL_PROVIDER=mta`). Rate counters are those of the API process; the workers’ are visible in Redis (`mta:rate:*`).","x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MtaStatus"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/mta/ips/{address}/warmup":{"post":{"operationId":"adminMtaIpWarmup","summary":"Start / stop the warm-up of an outbound IP of the built-in MTA (ADR-0008)","tags":["Admin"],"description":"The warm-up plan (`MTA_IP_WARMUP_PLAN`, default 50 → 20,000 e-mails/day over 10 days, then unlimited) caps daily sends from this IP; when every IP is at its cap, sends are deferred (replayed), with no effect on contacts.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["start","stop"]}},"required":["action"]}}}},"parameters":[{"schema":{"type":"string","maxLength":45},"in":"path","name":"address","required":true}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"address":{"type":"string"},"action":{"type":"string","enum":["start","stop"]},"warmup":{"anyOf":[{"type":"object","properties":{"started_at":{"type":"string"},"day":{"type":"number"},"daily_limit":{"type":["number","null"]},"sent_today":{"type":"number"}},"required":["started_at","day","daily_limit","sent_today"],"additionalProperties":false},{"type":"null"}]}},"required":["address","action","warmup"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/stats/by-tenant":{"get":{"operationId":"adminStatsByTenant","summary":"Delivery counters per tenant over a period (operator)","tags":["Admin"],"parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"in":"query","name":"from","required":false},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"in":"query","name":"to","required":false},{"schema":{"type":"string","enum":["day"]},"in":"query","name":"group_by","required":false}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"period":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["from","to"],"additionalProperties":false},"alert_floor":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"data":{"type":"array","items":{"type":"object","properties":{"sent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_hard":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_soft":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"complained":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unsubscribed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"tenant_id":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"}},"required":["sent","delivered","bounced_hard","bounced_soft","complained","unsubscribed","failed","tenant_id"],"additionalProperties":false}},"by_day":{"type":"array","items":{"type":"object","properties":{"sent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delivered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_hard":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bounced_soft":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"complained":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unsubscribed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"tenant_id":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"day":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["sent","delivered","bounced_hard","bounced_soft","complained","unsubscribed","failed","tenant_id","day"],"additionalProperties":false}}},"required":["period","alert_floor","data"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/templates":{"post":{"operationId":"createTemplate","summary":"Create a template","tags":["Templates"],"description":"The HTML body must reference `{{unsubscribe_url}}` (F-TPL-03) for a `marketing` template. Tracking pixels are inserted at render time according to `tracking` and the contact’s consent (F-TPL-04). A `transactional` template (ADR-0010) is exempt from the unsubscribe link and never measures performance.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateCreateInput"}}}},"x-required-scope":"templates:write","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"listTemplates","summary":"List templates","tags":["Templates"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false}],"x-required-scope":"templates:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Template"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/templates/{id}":{"get":{"operationId":"getTemplate","summary":"Template detail","tags":["Templates"],"parameters":[{"schema":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"templates:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"operationId":"updateTemplate","summary":"Update a template","tags":["Templates"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplatePatchInput"}}}},"parameters":[{"schema":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"templates:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"operationId":"deleteTemplate","summary":"Delete a template","tags":["Templates"],"description":"Refused (409 `resource_in_use`) if a non-archived sequence or a campaign references the template.","parameters":[{"schema":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"templates:write","responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/templates/{id}/render":{"post":{"operationId":"renderTemplate","summary":"Preview the rendering for a real or fictitious contact","tags":["Templates"],"description":"Applies exactly the sending rules: the performance pixel only appears if the contact has a valid tracking consent.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateRenderRequestInput"}}}},"parameters":[{"schema":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"templates:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateRenderResult"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/templates/{id}/test-send":{"post":{"operationId":"testSendTemplate","summary":"Send a test e-mail to a given address","tags":["Templates"],"description":"Queued like any send (asynchronous). No tracking pixel. With an `rt_test_` key, the message is captured in the sandbox.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateTestSendRequestInput"}}}},"parameters":[{"schema":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"templates:write","responses":{"202":{"description":"Accepted — processed asynchronously","content":{"application/json":{"schema":{"type":"object","properties":{"message_id":{"type":"string"}},"required":["message_id"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/tracking-domains":{"get":{"operationId":"listTrackingDomains","summary":"Tenant tracking domains and active base URL of public links","tags":["Templates"],"description":"Pixels, rewritten links and unsubscribe links of sends use `base_url`: the most recently verified custom domain (`source.kind = custom`), otherwise the platform subdomain `<slug>.<suffix>` (`platform`), otherwise the global base (`global`).","x-required-scope":"templates:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TrackingDomain"}},"active":{"anyOf":[{"$ref":"#/components/schemas/TrackingDomain"},{"type":"null"}]},"base_url":{"type":"string","description":"Base actually used for upcoming sends"},"source":{"type":"object","properties":{"kind":{"type":"string","enum":["custom","platform","global"]},"base_url":{"type":"string"}},"required":["kind","base_url"],"additionalProperties":false,"description":"Origin of the active base"}},"required":["data","active","base_url","source"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/t/o/{token}":{"get":{"operationId":"trackingPixel","summary":"Tracking pixel (deliverability or performance)","tags":["Public"],"description":"Always answers a 1×1 GIF. Deliverability pixel: only updates `last_open_date` (day). Performance pixel: records an open only if the tracking consent is valid at request time; otherwise no data is written.","parameters":[{"schema":{"type":"string","maxLength":2000},"in":"path","name":"token","required":true}],"security":[],"responses":{"200":{"description":"image/gif 1×1","content":{"application/json":{"schema":{"description":"image/gif 1×1"}}}}}}},"/t/c/{token}":{"get":{"operationId":"trackedLink","summary":"Redirect of a tracked link (F-TPL-05)","tags":["Public"],"description":"Redirects (302) to the original URL. The click is recorded only if the contact is active and has a valid `tracking_click_email` consent at request time; otherwise no data is written (NFR-RGPD-03/04).","parameters":[{"schema":{"type":"string","maxLength":2000},"in":"path","name":"token","required":true}],"security":[],"responses":{"302":{"description":"Found — redirect","content":{"application/json":{"schema":{}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/u/{token}":{"get":{"operationId":"unsubscribeLink","summary":"Unsubscribe link (one click)","tags":["Public"],"description":"Immediate tenant-wide unsubscribe: status `unsubscribed`, exit from every sequence.","parameters":[{"schema":{"type":"string","maxLength":2000},"in":"path","name":"token","required":true}],"security":[],"responses":{"200":{"description":"HTML confirmation page","content":{"application/json":{"schema":{"description":"HTML confirmation page"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"unsubscribeOneClick","summary":"One-click unsubscribe (RFC 8058, List-Unsubscribe-Post)","tags":["Public"],"parameters":[{"schema":{"type":"string","maxLength":2000},"in":"path","name":"token","required":true}],"security":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/webhooks/providers/{provider}":{"post":{"operationId":"receiveProviderWebhook","summary":"Provider webhook (feedback: delivered, bounces, complaints)","tags":["Public"],"description":"Header `X-Router-Signature: sha256=<hex HMAC-SHA256 of the raw body>` computed with the shared secret. `generic` format documented by the schema.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericProviderWebhookInput"}}}},"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":50},"in":"path","name":"provider","required":true}],"security":[],"responses":{"202":{"description":"Accepted — processed asynchronously","content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["accepted"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sandbox/messages":{"get":{"operationId":"listSandboxMessages","summary":"E-mails captured in the sandbox (test keys only)","tags":["Sandbox"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"in":"query","name":"contact_id","required":false},{"schema":{"type":"string","pattern":"^msg_[0-9a-z]{26}$","example":"msg_0123456789abcdefghjkmnpqrs"},"in":"query","name":"message_id","required":false}],"x-required-scope":"events:read","x-sandbox-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SandboxMessageSummary"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sandbox/messages/{id}":{"get":{"operationId":"getSandboxMessage","summary":"Full content of a captured e-mail","tags":["Sandbox"],"description":"Accepts the capture identifier (`sbx_…`) or the message identifier (`msg_…`).","parameters":[{"schema":{"type":"string","pattern":"^(sbx|msg)_[0-9a-z]{26}$"},"in":"path","name":"id","required":true}],"x-required-scope":"events:read","x-sandbox-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxMessage"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sandbox/events":{"post":{"operationId":"simulateProviderEvent","summary":"Simulate provider feedback (delivered, bounce, complaint) on a sandbox message","tags":["Sandbox"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxEventRequestInput"}}}},"x-required-scope":"suppressions:write","x-sandbox-only":true,"responses":{"202":{"description":"Accepted — processed asynchronously","content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"boolean","enum":[true]},"event_id":{"type":"string"}},"required":["accepted","event_id"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sequences":{"post":{"operationId":"createSequence","summary":"Create a sequence (status draft, version 1)","tags":["Sequences"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceCreateInput"}}}},"x-required-scope":"sequences:write","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sequence"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"listSequences","summary":"List sequences (cursor pagination, enrollment counters included)","tags":["Sequences"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","enum":["draft","active","paused","archived"]},"in":"query","name":"status","required":false}],"x-required-scope":"sequences:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Sequence"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sequences/{id}":{"get":{"operationId":"getSequence","summary":"Sequence detail (current version + enrollment counters)","tags":["Sequences"],"parameters":[{"schema":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"sequences:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sequence"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"operationId":"updateSequence","summary":"Update a sequence (draft: in place; active/paused: new version — F-SEQ-05)","tags":["Sequences"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequencePatchInput"}}}},"parameters":[{"schema":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"sequences:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sequence"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sequences/{id}/activate":{"post":{"operationId":"activateSequence","summary":"Lifecycle: activate","tags":["Sequences"],"parameters":[{"schema":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"sequences:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sequence"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sequences/{id}/pause":{"post":{"operationId":"pauseSequence","summary":"Lifecycle: pause","tags":["Sequences"],"parameters":[{"schema":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"sequences:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sequence"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sequences/{id}/archive":{"post":{"operationId":"archiveSequence","summary":"Lifecycle: archive","tags":["Sequences"],"parameters":[{"schema":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"sequences:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sequence"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sequences/{id}/enrollments":{"post":{"operationId":"enrollContact","summary":"Explicitly enroll a contact (API trigger)","tags":["Sequences"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrollmentCreateInput"}}}},"parameters":[{"schema":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"sequences:write","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Enrollment"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"listEnrollments","summary":"Enrollments of a sequence","tags":["Sequences"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","enum":["active","completed","exited"]},"in":"query","name":"status","required":false},{"schema":{"type":"string"},"in":"query","name":"step_id","required":false},{"schema":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"in":"query","name":"contact_id","required":false},{"schema":{"default":"true","type":"string","enum":["true","false"]},"in":"query","name":"main_only","required":false,"description":"F-SEQ-08: `false` to include branch enrollments (children of a `split`)"},{"schema":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"sequences:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Enrollment"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sequences/{id}/ab-tests/{step_id}/decide":{"post":{"operationId":"decideAbTest","summary":"Pick the winning variant of an ab_test step (F-SEQ-08)","tags":["Sequences"],"description":"The decision is frozen on the current version: subsequent enrollments receive the winning variant. Enrollments already served do not change.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbTestDecisionInput"}}}},"parameters":[{"schema":{"type":"string","pattern":"^seq_[0-9a-z]{26}$","example":"seq_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true},{"schema":{"type":"string","minLength":1,"maxLength":40},"in":"path","name":"step_id","required":true}],"x-required-scope":"sequences:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sequence"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/enrollments/{id}":{"get":{"operationId":"getEnrollment","summary":"Enrollment state: current step, next due time, history (F-SEQ-06)","tags":["Sequences"],"parameters":[{"schema":{"type":"string","pattern":"^enr_[0-9a-z]{26}$","example":"enr_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"sequences:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Enrollment"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"operationId":"exitEnrollment","summary":"Remove a contact from a sequence","tags":["Sequences"],"parameters":[{"schema":{"type":"string","pattern":"^enr_[0-9a-z]{26}$","example":"enr_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"sequences:write","responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/webhooks":{"post":{"operationId":"createWebhook","summary":"Create a webhook subscription (the secret is returned only once)","tags":["Webhooks"],"description":"Signed HTTP POST JSON delivery `X-Router-Signature: v1=<hmac-sha256(\"<timestamp>.<body>\")>`, retries with exponential backoff over 24 h, automatic disabling after 20 consecutive failures.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreateRequestInput"}}}},"x-required-scope":"webhooks:write","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"description":{"type":["string","null"]},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"consecutive_failures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"created_at":{"type":"string"},"updated_at":{"type":"string"},"secret":{"type":"string"}},"required":["id","url","events","description","status","disabled_reason","consecutive_failures","created_at","updated_at","secret"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"listWebhooks","summary":"List webhook subscriptions","tags":["Webhooks"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","enum":["active","disabled"]},"in":"query","name":"status","required":false}],"x-required-scope":"webhooks:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/webhooks/{id}":{"get":{"operationId":"getWebhook","summary":"Webhook subscription detail","tags":["Webhooks"],"parameters":[{"schema":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"webhooks:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"operationId":"patchWebhook","summary":"Update a subscription (URL, events, description) or reactivate it","tags":["Webhooks"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookPatchRequestInput"}}}},"parameters":[{"schema":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"webhooks:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"operationId":"deleteWebhook","summary":"Delete a webhook subscription (and its delivery log)","tags":["Webhooks"],"parameters":[{"schema":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"webhooks:write","responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/webhooks/{id}/rotate-secret":{"post":{"operationId":"rotateWebhookSecret","summary":"Rotate the signing secret (returned only once)","tags":["Webhooks"],"parameters":[{"schema":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"webhooks:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"description":{"type":["string","null"]},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"consecutive_failures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"created_at":{"type":"string"},"updated_at":{"type":"string"},"secret":{"type":"string"}},"required":["id","url","events","description","status","disabled_reason","consecutive_failures","created_at","updated_at","secret"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/webhooks/{id}/deliveries":{"get":{"operationId":"listWebhookDeliveries","summary":"Delivery log of a webhook","tags":["Webhooks"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","enum":["pending","delivered","failed","exhausted"]},"in":"query","name":"status","required":false},{"schema":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"webhooks:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/webhooks/{id}/test":{"post":{"operationId":"testWebhook","summary":"Send a `webhook.test` test event","tags":["Webhooks"],"parameters":[{"schema":{"type":"string","pattern":"^whk_[0-9a-z]{26}$","example":"whk_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"webhooks:write","responses":{"202":{"description":"Accepted — processed asynchronously","content":{"application/json":{"schema":{"type":"object","properties":{"delivery_id":{"type":"string","pattern":"^wdl_[0-9a-z]{26}$","example":"wdl_0123456789abcdefghjkmnpqrs"}},"required":["delivery_id"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/audit-logs":{"get":{"operationId":"listAuditLogs","summary":"Tenant audit log (F-TEN-06): who did what, with which key","tags":["Audit"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","pattern":"^key_[0-9a-z]{26}$","example":"key_0123456789abcdefghjkmnpqrs"},"in":"query","name":"key_id","required":false},{"schema":{"type":"string","enum":["POST","PUT","PATCH","DELETE"]},"in":"query","name":"method","required":false},{"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"},"in":"query","name":"occurred_after","required":false},{"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"},"in":"query","name":"occurred_before","required":false}],"x-required-scope":"audit:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AuditLog"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/tenants/{id}/audit-logs":{"get":{"operationId":"adminListTenantAuditLogs","summary":"Audit log of a tenant (operator)","tags":["Admin"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","pattern":"^key_[0-9a-z]{26}$","example":"key_0123456789abcdefghjkmnpqrs"},"in":"query","name":"key_id","required":false},{"schema":{"type":"string","enum":["POST","PUT","PATCH","DELETE"]},"in":"query","name":"method","required":false},{"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"},"in":"query","name":"occurred_after","required":false},{"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"},"in":"query","name":"occurred_before","required":false},{"schema":{"type":"string","pattern":"^ten_[0-9a-z]{26}$","example":"ten_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AuditLog"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/audit-logs":{"get":{"operationId":"adminListOperatorAuditLogs","summary":"Audit log of operator operations (all tenants or global operations)","tags":["Admin"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","pattern":"^key_[0-9a-z]{26}$","example":"key_0123456789abcdefghjkmnpqrs"},"in":"query","name":"key_id","required":false},{"schema":{"type":"string","enum":["POST","PUT","PATCH","DELETE"]},"in":"query","name":"method","required":false},{"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"},"in":"query","name":"occurred_after","required":false},{"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","example":"2026-09-07T14:32:00Z"},"in":"query","name":"occurred_before","required":false},{"schema":{"default":"all","type":"string","enum":["all","global"]},"in":"query","name":"scope","required":false,"description":"`global`: operations with no tenant involved"}],"x-operator-only":true,"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AuditLog"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/exports/schedules":{"post":{"operationId":"createExportSchedule","summary":"Create a scheduled export (daily, weekly, monthly)","tags":["Exports"],"description":"The exported period is the previous complete window (D-1, previous ISO week, previous month). Delivery: downloadable file (`download`) or push to a tenant webhook (`webhook`, event `export.completed` with a signed download URL valid 24 h).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportScheduleCreateRequestInput"}}}},"x-required-scope":"exports:write","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportSchedule"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"listExportSchedules","summary":"List scheduled exports","tags":["Exports"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","enum":["active","paused"]},"in":"query","name":"status","required":false}],"x-required-scope":"exports:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ExportSchedule"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/exports/schedules/{id}":{"get":{"operationId":"getExportSchedule","summary":"Scheduled export detail","tags":["Exports"],"parameters":[{"schema":{"type":"string","pattern":"^exs_[0-9a-z]{26}$","example":"exs_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"exports:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportSchedule"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"operationId":"patchExportSchedule","summary":"Update a scheduled export (pause, frequency, delivery…)","tags":["Exports"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportSchedulePatchRequestInput"}}}},"parameters":[{"schema":{"type":"string","pattern":"^exs_[0-9a-z]{26}$","example":"exs_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"exports:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportSchedule"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"operationId":"deleteExportSchedule","summary":"Delete a scheduled export (exports already generated are kept)","tags":["Exports"],"parameters":[{"schema":{"type":"string","pattern":"^exs_[0-9a-z]{26}$","example":"exs_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"exports:write","responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/exports/schedules/{id}/run":{"post":{"operationId":"runExportSchedule","summary":"Run a scheduled export immediately (previous period)","tags":["Exports"],"parameters":[{"schema":{"type":"string","pattern":"^exs_[0-9a-z]{26}$","example":"exs_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"exports:write","responses":{"202":{"description":"Accepted — processed asynchronously","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Export"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/exports":{"post":{"operationId":"createExport","summary":"On-demand export (period `params.from/to`, default: last 30 days)","tags":["Exports"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportCreateRequestInput"}}}},"x-required-scope":"exports:write","responses":{"202":{"description":"Accepted — processed asynchronously","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Export"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"listExports","summary":"List generated exports","tags":["Exports"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","enum":["pending","running","completed","failed"]},"in":"query","name":"status","required":false},{"schema":{"type":"string","pattern":"^exs_[0-9a-z]{26}$","example":"exs_0123456789abcdefghjkmnpqrs"},"in":"query","name":"schedule_id","required":false}],"x-required-scope":"exports:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Export"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/exports/{id}":{"get":{"operationId":"getExport","summary":"Status and metadata of an export","tags":["Exports"],"parameters":[{"schema":{"type":"string","pattern":"^exp_[0-9a-z]{26}$","example":"exp_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"exports:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Export"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/exports/{id}/download":{"get":{"operationId":"downloadExport","summary":"Download an export file (API key)","tags":["Exports"],"description":"File stream (`Content-Disposition`, `X-Content-SHA256`). 409 if the export is not ready, 410 if it has expired.","parameters":[{"schema":{"type":"string","pattern":"^exp_[0-9a-z]{26}$","example":"exp_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"exports:read","responses":{"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"410":{"description":"Gone — expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/exports/{id}/download/signed":{"get":{"operationId":"downloadExportSigned","summary":"Download an export through a signed URL (webhook delivery, 24 h, no API key)","tags":["Exports"],"description":"The file contains no personal data (opaque identifiers, counters, dates). The signature is an HMAC-SHA256 of `<export_id>.<exp>`; an invalid or expired signature answers 404.","parameters":[{"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"in":"query","name":"exp","required":true},{"schema":{"type":"string","minLength":16,"maxLength":128},"in":"query","name":"sig","required":true},{"schema":{"type":"string","pattern":"^exp_[0-9a-z]{26}$","example":"exp_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"security":[],"responses":{"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"410":{"description":"Gone — expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/campaigns":{"post":{"operationId":"createCampaign","summary":"Create a one-shot campaign (draft)","tags":["Campaigns"],"description":"A `marketing` template sent to an audience (list or segment). The campaign is created as `draft`; `POST …/schedule` schedules or starts it. With an `rt_test_` key, sends are captured in the sandbox.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignCreateInput"}}}},"x-required-scope":"campaigns:write","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"listCampaigns","summary":"List campaigns","tags":["Campaigns"],"parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","enum":["draft","scheduled","running","completed","cancelled","failed"]},"in":"query","name":"status","required":false}],"x-required-scope":"campaigns:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Campaign"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/campaigns/{id}":{"get":{"operationId":"getCampaign","summary":"Campaign detail (counters + aggregates)","tags":["Campaigns"],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9a-z]{26}$","example":"cmp_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"campaigns:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignDetail"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"operationId":"updateCampaign","summary":"Update a campaign (draft only)","tags":["Campaigns"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignPatchInput"}}}},"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9a-z]{26}$","example":"cmp_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"campaigns:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"operationId":"deleteCampaign","summary":"Delete a campaign (draft only)","tags":["Campaigns"],"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9a-z]{26}$","example":"cmp_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"campaigns:write","responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/campaigns/{id}/schedule":{"post":{"operationId":"scheduleCampaign","summary":"Schedule or start a campaign","tags":["Campaigns"],"description":"Draft → `scheduled`. Without `scheduled_at` (or with a past date), materialisation starts immediately (202); otherwise the scheduler starts it when due.","requestBody":{"required":true,"content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"scheduled_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]}}},{"type":"null"}]}}}},"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9a-z]{26}$","example":"cmp_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"campaigns:write","responses":{"202":{"description":"Accepted — processed asynchronously","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/campaigns/{id}/cancel":{"post":{"operationId":"cancelCampaign","summary":"Cancel a campaign (draft, scheduled or running)","tags":["Campaigns"],"description":"When running: messages still queued move to `suppressed` (reason `campaign_cancelled`) and do not leave; messages already sent are not affected.","parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9a-z]{26}$","example":"cmp_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"campaigns:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^cmp_[0-9a-z]{26}$","example":"cmp_0123456789abcdefghjkmnpqrs"},"name":{"type":"string"},"template_id":{"type":"string","pattern":"^tpl_[0-9a-z]{26}$","example":"tpl_0123456789abcdefghjkmnpqrs"},"audience":{"$ref":"#/components/schemas/CampaignAudience"},"mode":{"type":"string","enum":["live","test"],"description":"Send mode inherited from the key that created the campaign: `test` = captured (Sandbox), never sent."},"status":{"type":"string","enum":["draft","scheduled","running","completed","cancelled","failed"]},"scheduled_at":{"type":["string","null"]},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"audience_count":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"queued_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"last_error":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"suppressed_messages":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","template_id","audience","mode","status","scheduled_at","started_at","completed_at","audience_count","queued_count","skipped_count","last_error","created_at","updated_at","suppressed_messages"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/campaigns/{id}/preview-audience":{"post":{"operationId":"previewCampaignAudience","summary":"Count the audience and show a sample, without sending","tags":["Campaigns"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"limit":{"default":10,"type":"integer","minimum":1,"maximum":50}}},{"type":"null"}]}}}},"parameters":[{"schema":{"type":"string","pattern":"^cmp_[0-9a-z]{26}$","example":"cmp_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"campaigns:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sample":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^ctc_[0-9a-z]{26}$","example":"ctc_0123456789abcdefghjkmnpqrs"},"email":{"type":"string"},"status":{"type":"string"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]}},"required":["id","email","status","first_name","last_name"],"additionalProperties":false}}},"required":["count","sample"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/messages":{"post":{"operationId":"sendTransactionalMessage","summary":"Send a single transactional e-mail (asynchronous)","tags":["Messages"],"description":"Legal basis: contract / pre-contractual measures — no marketing opt-in required, but the “strong” suppression list (hard bounce, complaint, erasure) is honoured (409 `contact_suppressed`); a marketing unsubscribe does not block. The template must be of type `transactional` (422 `transactional_template_required`). Free address: no contact created, address not persisted. Queued: `Idempotency-Key` recommended.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalSendRequestInput"}}}},"x-required-scope":"messages:write","responses":{"202":{"description":"Accepted — processed asynchronously","content":{"application/json":{"schema":{"type":"object","properties":{"message_id":{"type":"string","pattern":"^msg_[0-9a-z]{26}$","example":"msg_0123456789abcdefghjkmnpqrs"}},"required":["message_id"],"additionalProperties":false}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/messages/{id}":{"get":{"operationId":"getMessage","summary":"Status of a message and its events","tags":["Messages"],"parameters":[{"schema":{"type":"string","pattern":"^msg_[0-9a-z]{26}$","example":"msg_0123456789abcdefghjkmnpqrs"},"in":"path","name":"id","required":true}],"x-required-scope":"events:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"400":{"description":"Bad Request — validation error (RFC 9457 problem, `code` = `validation_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized — missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden — insufficient scope, or tenant suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not Found — unknown resource, or resource of another tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict — state or uniqueness conflict (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Unprocessable Content — business rule refused (see `code`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too Many Requests — rate limit or tenant quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}},"servers":[{"url":"https://api.missivia.app"}],"security":[{"apiKey":[]}],"tags":[{"name":"Contacts"},{"name":"Lists"},{"name":"Segments"},{"name":"Sequences"},{"name":"Templates"},{"name":"Events & Stats"},{"name":"Suppressions"},{"name":"Jobs"},{"name":"Audit"},{"name":"Sandbox"},{"name":"Admin"},{"name":"Public"},{"name":"System"}]}