{"components":{"headers":{"CorrelationId":{"description":"Request correlation ID for logs and support.","schema":{"type":"string"}}},"parameters":{"OrganizationSlug":{"in":"path","name":"organization_slug","required":true,"schema":{"type":"string"}},"WorkspaceSlug":{"in":"path","name":"workspace_slug","required":true,"schema":{"type":"string"}}},"schemas":{"ArchiveResponse":{"properties":{"archived":{"type":"boolean"}},"required":["archived"],"type":"object"},"AudienceCreateRequest":{"examples":[{"minimum_interval_seconds":604800,"name":"Weekly newsletter","purpose":"Weekly GFA community update","slug":"weekly-newsletter"}],"properties":{"minimum_interval_seconds":{"maximum":2147483647,"minimum":0,"type":"integer"},"name":{"type":"string"},"purpose":{"type":"string"},"slug":{"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$","type":"string"}},"required":["name","slug","purpose"],"type":"object"},"AudienceCreateResponse":{"properties":{"audience":{"properties":{"id":{"type":"string"},"slug":{"type":"string"}},"required":["id","slug"],"type":"object"}},"required":["audience"],"type":"object"},"AudienceResponse":{"properties":{"audience":{"properties":{"active_member_count":{"type":"integer"},"id":{"type":"string"},"is_archived":{"type":"boolean"},"name":{"type":"string"},"purpose":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug","purpose","is_archived","active_member_count"],"type":"object"}},"required":["audience"],"type":"object"},"AudienceSubscribeRequest":{"examples":[{"contact_id":"contact-id","evidence":{"captured_at":"2026-07-25T00:00:00Z"},"source":"approved-form","wording_version":"newsletter-v1"}],"properties":{"contact_id":{"type":"string"},"evidence":{"additionalProperties":true,"type":"object"},"form_identifier":{"type":"string"},"source":{"type":"string"},"source_application":{"type":"string"},"wording_version":{"type":"string"}},"required":["contact_id","source","wording_version"],"type":"object"},"AudienceSubscribeResponse":{"properties":{"consent_event_id":{"type":"string"},"subscribed":{"type":"boolean"}},"required":["subscribed","consent_event_id"],"type":"object"},"AudienceUnsubscribeRequest":{"examples":[{"contact_id":"contact-id","source":"authorized_api"}],"properties":{"contact_id":{"type":"string"},"source":{"type":"string"}},"required":["contact_id"],"type":"object"},"AudienceUnsubscribeResponse":{"properties":{"scope":{"const":"audience","type":"string"},"unsubscribed":{"type":"boolean"}},"required":["unsubscribed","scope"],"type":"object"},"Automation":{"properties":{"activation_available":{"const":false,"type":"boolean"},"authoring_only":{"const":true,"type":"boolean"},"current_version":{"type":"integer"},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"enrollment_available":{"const":false,"type":"boolean"},"execution_available":{"const":false,"type":"boolean"},"id":{"type":"string"},"name":{"type":"string"},"review_ready_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}]},"review_ready_by_gfavip_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"review_ready_version":{"anyOf":[{"type":"integer"},{"type":"null"}]},"selected_version":{"properties":{"change_notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"format":"date-time","type":"string"},"created_by_gfavip_id":{"type":"string"},"definition":{"$ref":"#/components/schemas/AutomationDefinition"},"definition_checksum":{"type":"string"},"id":{"type":"string"},"preview":{"additionalProperties":true,"type":"object"},"trigger_type":{"type":"string"},"validation":{"$ref":"#/components/schemas/AutomationValidation"},"version":{"type":"integer"}},"required":["id","version","trigger_type","definition_checksum","validation","preview","definition","change_notes","created_by_gfavip_id","created_at"],"type":"object"},"slug":{"type":"string"},"status":{"enum":["draft","ready_for_review","archived"],"type":"string"},"versions":{"items":{"$ref":"#/components/schemas/AutomationVersionSummary"},"type":"array"},"workspace_id":{"type":"string"}},"required":["id","workspace_id","name","slug","description","status","current_version","review_ready_version","review_ready_by_gfavip_id","review_ready_at","authoring_only","execution_available","activation_available","enrollment_available","selected_version"],"type":"object"},"AutomationCreateRequest":{"examples":[{"change_notes":"Initial non-executable shell","definition":{"edges":[],"nodes":[{"config":{},"key":"finish","type":"end"}],"start_node":"finish","trigger":{"config":{},"type":"manual"}},"description":"Authoring-only synthetic workflow","name":"Lead magnet delivery","slug":"lead-magnet-delivery"}],"properties":{"change_notes":{"type":"string"},"definition":{"$ref":"#/components/schemas/AutomationDefinition"},"description":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["name","slug","definition"],"type":"object"},"AutomationDefinition":{"properties":{"edges":{"items":{"$ref":"#/components/schemas/AutomationEdgeDefinition"},"maxItems":200,"type":"array"},"nodes":{"items":{"$ref":"#/components/schemas/AutomationNodeDefinition"},"maxItems":100,"minItems":1,"type":"array"},"start_node":{"type":"string"},"trigger":{"$ref":"#/components/schemas/AutomationTrigger"}},"required":["trigger","start_node","nodes","edges"],"type":"object"},"AutomationEdgeDefinition":{"properties":{"branch":{"type":"string"},"condition":{"additionalProperties":true,"type":"object"},"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to","branch"],"type":"object"},"AutomationEnrollment":{"properties":{"automation_id":{"type":"string"},"automation_version_id":{"type":"string"},"completed_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}]},"current_node_key":{"anyOf":[{"type":"string"},{"type":"null"}]},"enrolled_at":{"format":"date-time","type":"string"},"events":{"items":{"type":"object"},"type":"array"},"id":{"type":"string"},"provider_calls":{"const":0,"type":"integer"},"state":{"type":"string"},"steps":{"items":{"type":"object"},"type":"array"},"synthetic":{"const":true,"type":"boolean"},"webhook_calls":{"const":0,"type":"integer"},"workspace_id":{"type":"string"}},"required":["id","workspace_id","automation_id","automation_version_id","state","synthetic","enrolled_at","provider_calls","webhook_calls"],"type":"object"},"AutomationEnrollmentControlRequest":{"examples":[{"reason":"synthetic operator rehearsal","step_id":"failed-synthetic-step-id"}],"properties":{"reason":{"anyOf":[{"type":"string"},{"type":"null"}]},"step_id":{"anyOf":[{"type":"string"},{"type":"null"}]}},"type":"object"},"AutomationEnrollmentListResponse":{"properties":{"enrollments":{"items":{"$ref":"#/components/schemas/AutomationEnrollment"},"type":"array"},"production_enrollment_available":{"const":false,"type":"boolean"},"synthetic_only":{"const":true,"type":"boolean"}},"required":["enrollments","synthetic_only","production_enrollment_available"],"type":"object"},"AutomationEnrollmentResponse":{"properties":{"enrollment":{"$ref":"#/components/schemas/AutomationEnrollment"}},"required":["enrollment"],"type":"object"},"AutomationListResponse":{"properties":{"authoring_only":{"const":true,"type":"boolean"},"automations":{"items":{"$ref":"#/components/schemas/Automation"},"type":"array"},"execution_available":{"const":false,"type":"boolean"}},"required":["automations","authoring_only","execution_available"],"type":"object"},"AutomationNodeDefinition":{"properties":{"config":{"additionalProperties":true,"type":"object"},"key":{"type":"string"},"type":{"enum":["send_email","wait_duration","wait_until_date","add_tag","remove_tag","add_audience","remove_audience","update_contact_field","adjust_score","decision","end"],"type":"string"}},"required":["key","type","config"],"type":"object"},"AutomationResponse":{"properties":{"automation":{"$ref":"#/components/schemas/Automation"}},"required":["automation"],"type":"object"},"AutomationReviewReadyRequest":{"examples":[{"definition_checksum":"sha256-definition-checksum","version_id":"automation-version-id"}],"properties":{"definition_checksum":{"type":"string"},"version_id":{"type":"string"}},"required":["version_id","definition_checksum"],"type":"object"},"AutomationSyntheticEnrollmentRequest":{"examples":[{"contact_id":"synthetic-contact-id","synthetic_context_id":"synthetic-rehearsal-id"}],"properties":{"contact_id":{"type":"string"},"synthetic_context_id":{"type":"string"}},"required":["contact_id","synthetic_context_id"],"type":"object"},"AutomationTrigger":{"properties":{"config":{"additionalProperties":true,"type":"object"},"type":{"enum":["audience_subscribed","tag_added","tag_removed","contact_field_changed","contact_date","recurring_schedule","api_event","manual"],"type":"string"}},"required":["type","config"],"type":"object"},"AutomationValidation":{"properties":{"authoring_only":{"const":true,"type":"boolean"},"dependencies":{"items":{"additionalProperties":true,"type":"object"},"type":"array"},"dependency_counts":{"additionalProperties":true,"type":"object"},"execution_available":{"const":false,"type":"boolean"},"reconstruction_review":{"additionalProperties":true,"type":"object"},"source_provenance":{"$ref":"#/components/schemas/RecoveredSourceProvenance"},"structural_errors":{"items":{"type":"string"},"type":"array"},"valid":{"type":"boolean"},"warnings":{"items":{"type":"string"},"type":"array"}},"required":["valid","structural_errors","dependencies","dependency_counts","warnings","authoring_only","execution_available"],"type":"object"},"AutomationVersionRequest":{"examples":[{"change_notes":"Reviewed source definition","definition":{"edges":[],"nodes":[{"config":{},"key":"finish","type":"end"}],"start_node":"finish","trigger":{"config":{},"type":"manual"}}}],"properties":{"change_notes":{"type":"string"},"definition":{"$ref":"#/components/schemas/AutomationDefinition"}},"required":["definition"],"type":"object"},"AutomationVersionSummary":{"properties":{"change_notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"format":"date-time","type":"string"},"created_by_gfavip_id":{"type":"string"},"definition_checksum":{"type":"string"},"id":{"type":"string"},"trigger_type":{"type":"string"},"version":{"type":"integer"}},"required":["id","version","trigger_type","definition_checksum","change_notes","created_by_gfavip_id","created_at"],"type":"object"},"Campaign":{"properties":{"current_version":{"type":"integer"},"draft":{"properties":{"audience_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"audience_ids":{"items":{"type":"string"},"type":"array"},"content_version_id":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"sender_identity_id":{"type":"string"},"version":{"type":"integer"}},"required":["id","version","name","audience_id","audience_ids","sender_identity_id","content_version_id"],"type":"object"},"id":{"type":"string"},"status":{"type":"string"}},"required":["id","status","current_version","draft"],"type":"object"},"CampaignDraftRequest":{"examples":[{"audience_id":"audience-id","content_version_id":"content-version-id","name":"Weekly GFA update","notes":"Draft only","sender_identity_id":"sender-id"}],"properties":{"audience_id":{"type":"string"},"content_version_id":{"type":"string"},"name":{"type":"string"},"notes":{"type":"string"},"sender_identity_id":{"type":"string"}},"required":["name","audience_id","sender_identity_id","content_version_id"],"type":"object"},"CampaignReportResponse":{"properties":{"campaign_run":{"$ref":"#/components/schemas/CampaignRun"},"report":{"additionalProperties":true,"type":"object"}},"required":["campaign_run","report"],"type":"object"},"CampaignResponse":{"properties":{"campaign":{"$ref":"#/components/schemas/Campaign"}},"required":["campaign"],"type":"object"},"CampaignRun":{"properties":{"campaign_id":{"type":"string"},"excluded_count":{"type":"integer"},"exclusion_counts":{"additionalProperties":true,"type":"object"},"failed_count":{"type":"integer"},"id":{"type":"string"},"included_count":{"type":"integer"},"scheduled_for":{"format":"date-time","type":"string"},"sent_count":{"type":"integer"},"snapshot_id":{"type":"string"},"state":{"type":"string"}},"required":["id","campaign_id","snapshot_id","state","scheduled_for","included_count","excluded_count","sent_count","failed_count","exclusion_counts"],"type":"object"},"CampaignRunResponse":{"properties":{"campaign_run":{"$ref":"#/components/schemas/CampaignRun"}},"required":["campaign_run"],"type":"object"},"CampaignWebhookRequest":{"examples":[{"campaign_webhook_secret":"whsec_example","campaign_webhook_url":"https://console.gfavip.com/webhooks/campaign-events"}],"properties":{"campaign_webhook_secret":{"anyOf":[{"type":"string"},{"type":"null"}]},"campaign_webhook_url":{"anyOf":[{"type":"string"},{"type":"null"}]}},"type":"object"},"CampaignWebhookResponse":{"properties":{"campaign_webhook":{"properties":{"secret_set":{"type":"boolean"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["url","secret_set"],"type":"object"}},"required":["campaign_webhook"],"type":"object"},"Contact":{"properties":{"company":{"anyOf":[{"type":"string"},{"type":"null"}]},"country_code":{"anyOf":[{"type":"string"},{"type":"null"}]},"custom_fields":{"additionalProperties":true,"type":"object"},"email":{"type":"string"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}]},"id":{"type":"string"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}]},"legacy_consent_classification":{"anyOf":[{"type":"string"},{"type":"null"}]},"normalized_email":{"type":"string"},"tags":{"items":{"type":"string"},"type":"array"}},"required":["id","email","normalized_email","first_name","last_name","company","country_code","legacy_consent_classification","tags","custom_fields"],"type":"object"},"ContactFieldDefinitionRequest":{"examples":[{"field_key":"industry","field_type":"single_choice","label":"Industry","options":["commerce","technology"]}],"properties":{"field_key":{"pattern":"^[a-z][a-z0-9_]{0,99}$","type":"string"},"field_type":{"enum":["text","long_text","integer","decimal","boolean","date","datetime","single_choice","multiple_choice","url"],"type":"string"},"label":{"type":"string"},"options":{"items":{"type":"string"},"type":"array"}},"required":["field_key","label","field_type"],"type":"object"},"ContactFieldDefinitionResponse":{"properties":{"field_definition":{"properties":{"field_key":{"type":"string"},"field_type":{"type":"string"},"id":{"type":"string"},"version":{"type":"integer"}},"required":["id","field_key","field_type","version"],"type":"object"}},"required":["field_definition"],"type":"object"},"ContactResponse":{"properties":{"contact":{"$ref":"#/components/schemas/Contact"}},"required":["contact"],"type":"object"},"ContactUpsertRequest":{"examples":[{"country_code":"US","email":"person@example.com","first_name":"Person","source":"approved-form","tags":["newsletter"]}],"properties":{"company":{"anyOf":[{"type":"string"},{"type":"null"}]},"country_code":{"anyOf":[{"type":"string"},{"type":"null"}]},"custom_fields":{"additionalProperties":true,"type":"object"},"email":{"format":"email","type":"string"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}]},"is_legacy":{"type":"boolean"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}]},"legacy_consent_evidence":{"additionalProperties":true,"type":"object"},"locale":{"anyOf":[{"type":"string"},{"type":"null"}]},"phone":{"anyOf":[{"type":"string"},{"type":"null"}]},"source":{"type":"string"},"source_identifier":{"type":"string"},"source_metadata":{"additionalProperties":true,"type":"object"},"source_workspace":{"type":"string"},"tags":{"items":{"type":"string"},"type":"array"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["email","source"],"type":"object"},"ContactUpsertResponse":{"properties":{"contact":{"$ref":"#/components/schemas/Contact"},"created":{"type":"boolean"}},"required":["contact","created"],"type":"object"},"ContentValidation":{"properties":{"images":{"type":"integer"},"links":{"type":"integer"},"missing_defaults":{"items":{"type":"string"},"type":"array"},"plain_text_generated":{"type":"boolean"},"review_warnings":{"items":{"type":"string"},"type":"array"},"source_provenance":{"$ref":"#/components/schemas/RecoveredSourceProvenance"},"stripped":{"$ref":"#/components/schemas/StrippedMarkup"},"tokens":{"items":{"type":"string"},"type":"array"},"unsubscribe_present":{"type":"boolean"},"valid":{"type":"boolean"}},"required":["valid","links","images","tokens","missing_defaults","plain_text_generated","unsubscribe_present"],"type":"object"},"ContentVersionRequest":{"examples":[{"html":"<p>Hello {{ first_name }}</p><p><a href=\"{{ unsubscribe_url }}\">Unsubscribe</a></p>","personalization_defaults":{"first_name":"there"},"plain_text":"Hello {{ first_name }}\n\nUnsubscribe: {{ unsubscribe_url }}","preheader":"This week's GFA update","subject":"Hello {{ first_name }}"}],"properties":{"html":{"type":"string"},"personalization_defaults":{"additionalProperties":{"type":"string"},"type":"object"},"plain_text":{"type":"string"},"preheader":{"type":"string"},"subject":{"maxLength":300,"type":"string"}},"required":["subject","html"],"type":"object"},"ContentVersionResponse":{"properties":{"content_version":{"properties":{"id":{"type":"string"},"template_id":{"type":"string"},"validation":{"$ref":"#/components/schemas/ContentValidation"},"version":{"type":"integer"}},"required":["id","template_id","version","validation"],"type":"object"}},"required":["content_version"],"type":"object"},"CsvImport":{"properties":{"approval_checksum":{"anyOf":[{"type":"string"},{"type":"null"}]},"approved_by_gfavip_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"attempt_count":{"type":"integer"},"completed_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}]},"consent_policy":{"type":"string"},"created_at":{"format":"date-time","type":"string"},"error":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}]},"expires_at":{"format":"date-time","type":"string"},"file_sha256":{"type":"string"},"filename":{"type":"string"},"headers":{"items":{"type":"string"},"type":"array"},"id":{"type":"string"},"mapping":{"additionalProperties":{"type":"string"},"type":"object"},"payload_retained":{"type":"boolean"},"payload_size":{"type":"integer"},"policy":{"additionalProperties":true,"type":"object"},"report":{"additionalProperties":true,"type":"object"},"report_checksum":{"anyOf":[{"type":"string"},{"type":"null"}]},"requested_by_gfavip_id":{"type":"string"},"source_label":{"type":"string"},"status":{"type":"string"}},"required":["id","status","filename","source_label","file_sha256","payload_size","payload_retained","headers","mapping","consent_policy","policy","report","report_checksum","approval_checksum","requested_by_gfavip_id","approved_by_gfavip_id","attempt_count","created_at","expires_at","completed_at","error"],"type":"object"},"CsvImportApprovalRequest":{"examples":[{"confirmation":"APPLY CSV IMPORT job-id TO gfa-community/gfa-community"}],"properties":{"confirmation":{"type":"string"}},"required":["confirmation"],"type":"object"},"CsvImportListResponse":{"properties":{"imports":{"items":{"$ref":"#/components/schemas/CsvImport"},"type":"array"}},"required":["imports"],"type":"object"},"CsvImportMappingProfileListResponse":{"properties":{"profiles":{"items":{"properties":{"id":{"type":"string"},"mapping":{"additionalProperties":true,"type":"object"},"mapping_checksum":{"type":"string"},"name":{"type":"string"},"policy":{"additionalProperties":true,"type":"object"}},"required":["id","name","mapping","policy","mapping_checksum"],"type":"object"},"type":"array"}},"required":["profiles"],"type":"object"},"CsvImportMappingRequest":{"examples":[{"consent_policy":"status_column","mapping":{"email":"Email","first_name":"First Name","status":"Status"},"policy":{"consent_basis":"Documented newsletter opt-in field.","consent_source":"documented-event-registration","default_status":"review_required","evidence_reference":"approved-registration-export","static_tags":["event"],"status_values":{"subscribed":"subscribed","unsubscribed":"audience_unsubscribe"},"wording_version":"event-form-v2"}}],"properties":{"consent_policy":{"enum":["review_required","explicit_opt_in","status_column"],"type":"string"},"mapping":{"additionalProperties":{"type":"string"},"type":"object"},"policy":{"additionalProperties":true,"type":"object"},"profile_id":{"type":"string"},"save_profile_name":{"type":"string"}},"required":["mapping","consent_policy","policy"],"type":"object"},"CsvImportResponse":{"properties":{"import":{"$ref":"#/components/schemas/CsvImport"}},"required":["import"],"type":"object"},"DomainProviderRequest":{"examples":[{"dkim_selector":"smtp","provider_connection_id":"provider-connection-id","provider_domain_reference":"mail.example.com"}],"properties":{"dkim_selector":{"type":"string"},"provider_connection_id":{"type":"string"},"provider_domain_reference":{"type":"string"}},"required":["provider_connection_id","dkim_selector"],"type":"object"},"DomainVerifyResponse":{"properties":{"check":{"properties":{"evidence":{"additionalProperties":true,"type":"object"},"id":{"type":"string"},"is_ready":{"type":"boolean"}},"required":["id","is_ready","evidence"],"type":"object"},"sending_domain":{"$ref":"#/components/schemas/SendingDomain"}},"required":["sending_domain","check"],"type":"object"},"EligibilityResponse":{"properties":{"eligibility":{"properties":{"audience_id":{"type":"string"},"contact_id":{"type":"string"},"eligible":{"type":"boolean"},"evaluated_at":{"format":"date-time","type":"string"},"reasons":{"items":{"type":"string"},"type":"array"},"workspace_id":{"type":"string"}},"required":["eligible","reasons","contact_id","audience_id","workspace_id","evaluated_at"],"type":"object"}},"required":["eligibility"],"type":"object"},"EmailTemplateArchiveRequest":{"examples":[{"archived":true}],"properties":{"archived":{"type":"boolean"}},"type":"object"},"EmailTemplateArchiveResponse":{"properties":{"email_template":{"properties":{"archived":{"type":"boolean"},"id":{"type":"string"}},"required":["id","archived"],"type":"object"}},"required":["email_template"],"type":"object"},"EmailTemplateRequest":{"examples":[{"description":"Versioned weekly newsletter","name":"Weekly update","slug":"weekly-update"}],"properties":{"description":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["name","slug"],"type":"object"},"EmailTemplateResponse":{"properties":{"email_template":{"properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"],"type":"object"}},"required":["email_template"],"type":"object"},"HealthResponse":{"properties":{"production_sending_enabled":{"type":"boolean"},"role":{"type":"string"},"service":{"type":"string"},"status":{"type":"string"}},"required":["status","service","role","production_sending_enabled"],"type":"object"},"MailgunWebhookEnvelope":{"examples":[{"event-data":{"event":"delivered","id":"provider-event-id","timestamp":1784937600},"signature":{"signature":"provider-supplied-hmac","timestamp":"1784937600","token":"provider-supplied-token"}}],"properties":{"event-data":{"properties":{"event":{"enum":["accepted","delivered","failed","opened","clicked","unsubscribed","complained"],"type":"string"},"id":{"type":"string"},"timestamp":{"type":"number"}},"required":["id","event","timestamp"],"type":"object"},"signature":{"properties":{"signature":{"type":"string"},"timestamp":{"type":"string"},"token":{"type":"string"}},"required":["timestamp","token","signature"],"type":"object"}},"required":["signature","event-data"],"type":"object"},"MailgunWebhookResponse":{"properties":{"id":{"type":"string"},"status":{"enum":["processed","duplicate"],"type":"string"}},"required":["status","id"],"type":"object"},"MeResponse":{"examples":[{"auth_method":"bearer","csrf_token":null,"user":{"gfavip_user_id":"stable-wallet-user-id","identity_type":"agent","platform_role":null,"username":"pl-arthur-blaze"},"workspaces":[{"is_archived":false,"organization":"gfa-community","role":"editor","workspace":"gfa-community"}]}],"properties":{"auth_method":{"enum":["bearer","session","service"],"type":"string"},"csrf_token":{"anyOf":[{"type":"string"},{"type":"null"}]},"user":{"$ref":"#/components/schemas/User"},"workspaces":{"items":{"$ref":"#/components/schemas/Membership"},"type":"array"}},"required":["user","auth_method","csrf_token","workspaces"],"type":"object"},"Membership":{"properties":{"is_archived":{"type":"boolean"},"organization":{"type":"string"},"role":{"type":"string"},"workspace":{"type":"string"}},"required":["organization","workspace","role","is_archived"],"type":"object"},"PreferenceTokenRequest":{"examples":[{"audience_id":"audience-id","scope":"audience"}],"properties":{"audience_id":{"type":"string"},"scope":{"enum":["audience","workspace"],"type":"string"}},"required":["scope"],"type":"object"},"PreferenceTokenResponse":{"properties":{"one_click_url":{"format":"uri","type":"string"},"preference_url":{"format":"uri","type":"string"}},"required":["preference_url","one_click_url"],"type":"object"},"PreferenceUnsubscribeResponse":{"properties":{"scope":{"type":"string"},"unsubscribed":{"type":"boolean"}},"required":["unsubscribed","scope"],"type":"object"},"Preflight":{"properties":{"checks":{"items":{"$ref":"#/components/schemas/PreflightCheck"},"type":"array"},"completed_at":{"format":"date-time","type":"string"},"id":{"type":"string"},"report_checksum":{"type":"string"},"requested_by_gfavip_id":{"type":"string"},"status":{"enum":["passed","blocked"],"type":"string"},"summary":{"properties":{"blocked":{"type":"integer"},"passed":{"type":"integer"},"warnings":{"type":"integer"}},"required":["passed","blocked","warnings"],"type":"object"},"workspace_id":{"type":"string"}},"required":["id","workspace_id","status","summary","checks","report_checksum","requested_by_gfavip_id","completed_at"],"type":"object"},"PreflightCheck":{"properties":{"code":{"type":"string"},"detail":{"type":"string"},"evidence":{"additionalProperties":true,"type":"object"},"label":{"type":"string"},"remediation":{"type":"string"},"status":{"enum":["pass","warn","block"],"type":"string"}},"required":["code","label","status","detail"],"type":"object"},"PreflightResponse":{"properties":{"preflight":{"anyOf":[{"$ref":"#/components/schemas/Preflight"},{"type":"null"}]}},"required":["preflight"],"type":"object"},"ProductionActivationRequest":{"examples":[{"confirmation":"ACTIVATE PRODUCTION SENDING"}],"properties":{"confirmation":{"const":"ACTIVATE PRODUCTION SENDING","type":"string"}},"required":["confirmation"],"type":"object"},"ProviderActivationRequest":{"examples":[{"confirmation":"ENABLE TEST CONNECTION"}],"properties":{"confirmation":{"const":"ENABLE TEST CONNECTION","type":"string"}},"required":["confirmation"],"type":"object"},"ProviderConnection":{"properties":{"connection_state":{"type":"string"},"credential_env_key":{"type":"string"},"credential_value_exposed":{"const":false,"type":"boolean"},"id":{"type":"string"},"is_active":{"type":"boolean"},"name":{"type":"string"},"provider":{"const":"mailgun","type":"string"},"region":{"type":"string"},"webhook_signing_env_key":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","name","provider","region","credential_env_key","webhook_signing_env_key","connection_state","is_active","credential_value_exposed"],"type":"object"},"ProviderConnectionRequest":{"examples":[{"credential_env_key":"MAILGUN_API_KEY_GFA","name":"Mailgun US","region":"us","webhook_signing_env_key":"MAILGUN_WEBHOOK_SIGNING_KEY_GFA"}],"properties":{"credential_env_key":{"type":"string"},"name":{"type":"string"},"region":{"enum":["us","eu"],"type":"string"},"webhook_signing_env_key":{"type":"string"}},"required":["name","credential_env_key"],"type":"object"},"ProviderConnectionResponse":{"properties":{"provider_connection":{"$ref":"#/components/schemas/ProviderConnection"}},"required":["provider_connection"],"type":"object"},"ProviderEventReplayResponse":{"properties":{"provider_event":{"properties":{"event_type":{"type":"string"},"id":{"type":"string"},"processing_state":{"type":"string"}},"required":["id","processing_state","event_type"],"type":"object"}},"required":["provider_event"],"type":"object"},"ReadinessResponse":{"properties":{"database":{"type":"string"},"status":{"type":"string"}},"required":["status","database"],"type":"object"},"RecoveredSourceProvenance":{"properties":{"checksum_manifest_sha256":{"type":"string"},"operator_review_required":{"const":true,"type":"boolean"},"protected_source_outside_git":{"const":true,"type":"boolean"},"source_checksum":{"type":"string"},"source_hashes":{"additionalProperties":true,"type":"object"},"source_id":{"type":"string"},"source_object_id":{"oneOf":[{"type":"string"},{"type":"integer"}]},"source_object_type":{"enum":["email","campaign"],"type":"string"},"source_repository_commit":{"type":"string"},"source_system":{"enum":["mautic"],"type":"string"},"transformation":{"additionalProperties":true,"type":"object"},"workflow_graph_sha256":{"type":"string"}},"required":["source_system","source_object_type","source_object_id","source_id","source_repository_commit","checksum_manifest_sha256","protected_source_outside_git","operator_review_required"],"type":"object"},"Rehearsal":{"properties":{"created_at":{"format":"date-time","type":"string"},"event_counts":{"additionalProperties":true,"type":"object"},"id":{"type":"string"},"reconciliation":{"additionalProperties":true,"type":"object"},"state":{"type":"string"},"test_send_request_id":{"type":"string"},"verified_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}]}},"required":["id","test_send_request_id","state","event_counts","reconciliation","created_at","verified_at"],"type":"object"},"RehearsalRequest":{"examples":[{"confirmation":"RUN CONTROLLED REHEARSAL","content_version_id":"content-version-id","recipient_email":"allowlisted@example.com","sender_identity_id":"sender-id"}],"properties":{"confirmation":{"const":"RUN CONTROLLED REHEARSAL","type":"string"},"content_version_id":{"type":"string"},"recipient_email":{"format":"email","type":"string"},"sender_identity_id":{"type":"string"}},"required":["sender_identity_id","content_version_id","recipient_email","confirmation"],"type":"object"},"RehearsalResponse":{"properties":{"rehearsal":{"$ref":"#/components/schemas/Rehearsal"}},"required":["rehearsal"],"type":"object"},"ResolveSuppressionRequest":{"examples":[{"resolution_reason":"Reviewed and cleared by an authorized operator"}],"properties":{"resolution_reason":{"type":"string"}},"required":["resolution_reason"],"type":"object"},"ResolvedResponse":{"properties":{"resolved":{"type":"boolean"}},"required":["resolved"],"type":"object"},"ScheduleRequest":{"examples":[{"scheduled_for":"2026-08-01T10:00:00+07:00"}],"properties":{"scheduled_for":{"format":"date-time","type":"string"}},"required":["scheduled_for"],"type":"object"},"SenderActivationResponse":{"properties":{"sender_identity":{"properties":{"id":{"type":"string"},"is_enabled":{"type":"boolean"}},"required":["id","is_enabled"],"type":"object"}},"required":["sender_identity"],"type":"object"},"SenderIdentity":{"properties":{"display_name":{"type":"string"},"from_address":{"type":"string"},"id":{"type":"string"},"is_enabled":{"type":"boolean"},"reply_to":{"type":"string"},"verification_state":{"type":"string"}},"required":["id","display_name","from_address","reply_to","verification_state","is_enabled"],"type":"object"},"SenderIdentityRequest":{"examples":[{"display_name":"GFA Community","from_address":"news@mail.example.com","reply_to":"support@example.com","sending_domain_id":"sending-domain-id"}],"properties":{"display_name":{"type":"string"},"from_address":{"format":"email","type":"string"},"reply_to":{"format":"email","type":"string"},"sending_domain_id":{"type":"string"}},"required":["sending_domain_id","display_name","from_address","reply_to"],"type":"object"},"SenderIdentityResponse":{"properties":{"sender_identity":{"$ref":"#/components/schemas/SenderIdentity"}},"required":["sender_identity"],"type":"object"},"SendingDomain":{"properties":{"alignment_state":{"type":"string"},"dkim_state":{"type":"string"},"dmarc_state":{"type":"string"},"domain_name":{"type":"string"},"id":{"type":"string"},"is_ready":{"type":"boolean"},"quota_state":{"type":"string"},"spf_state":{"type":"string"},"verification_state":{"type":"string"}},"required":["id","domain_name","verification_state","spf_state","dkim_state","dmarc_state","alignment_state","quota_state","is_ready"],"type":"object"},"SendingDomainReadinessRequest":{"examples":[{"alignment_state":"not_checked","dkim_state":"pending","dmarc_state":"pending","notes":"Pending live verification","quota_state":"not_checked","spf_state":"pending","verification_state":"pending"}],"properties":{"alignment_state":{"enum":["not_checked","aligned","misaligned"],"type":"string"},"dkim_state":{"enum":["not_checked","pending","verified","failed"],"type":"string"},"dmarc_state":{"enum":["not_checked","pending","verified","failed"],"type":"string"},"notes":{"type":"string"},"quota_state":{"enum":["not_checked","approved","insufficient"],"type":"string"},"spf_state":{"enum":["not_checked","pending","verified","failed"],"type":"string"},"verification_state":{"enum":["not_checked","pending","verified","failed"],"type":"string"}},"type":"object"},"SendingDomainRequest":{"examples":[{"domain_name":"mail.example.com","tracking_domain":"track.example.com"}],"properties":{"domain_name":{"type":"string"},"notes":{"type":"string"},"tracking_domain":{"type":"string"}},"required":["domain_name"],"type":"object"},"SendingDomainResponse":{"properties":{"sending_domain":{"$ref":"#/components/schemas/SendingDomain"}},"required":["sending_domain"],"type":"object"},"StrippedMarkup":{"description":"What the sanitizer removed from the submitted HTML. `valid` stays true when these lists are non-empty: the version is stored, but the stored `sanitized_html` no longer contains the listed markup, and that is what is sent. Treat any non-empty list as a defect in the submitted HTML and repost with allowlisted markup. See /skill.md, 'Email HTML that survives sanitizing'.","properties":{"attributes":{"items":{"type":"string"},"type":"array"},"css_properties":{"items":{"type":"string"},"type":"array"},"protocols":{"items":{"type":"string"},"type":"array"},"tags":{"items":{"type":"string"},"type":"array"}},"required":["tags","attributes","css_properties","protocols"],"type":"object"},"SubscriptionSourceAudiencesResponse":{"properties":{"audiences":{"items":{"properties":{"id":{"format":"uuid","type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"],"type":"object"},"type":"array"},"schema_version":{"const":"connect.subscription-source-audiences.v1","type":"string"},"source_id":{"format":"uuid","type":"string"}},"required":["schema_version","source_id","audiences"],"type":"object"},"SubscriptionSourceCreateRequest":{"examples":[{"allowed_audience_ids":["22222222-2222-4222-8222-222222222222"],"allowed_origins":["https://my.lifeisshortdoitnow.com"],"display_name":"MemoUpdate signup form","slug":"memoupdate-signup"},{"allowed_origins":["https://my.lifeisshortdoitnow.com"],"allows_all_audiences":true,"display_name":"MemoUpdate signup form","slug":"memoupdate-everything"}],"properties":{"allowed_audience_ids":{"items":{"format":"uuid","type":"string"},"type":"array"},"allowed_origins":{"items":{"format":"uri","type":"string"},"type":"array"},"allows_all_audiences":{"type":"boolean"},"display_name":{"type":"string"},"slug":{"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$","type":"string"}},"required":["slug","display_name","allowed_origins"],"type":"object"},"SubscriptionSourceEventRequest":{"additionalProperties":false,"examples":[{"captured_at":"2026-07-29T00:00:00Z","consent":{"privacy_policy_url":"https://lifeisshortdoitnow.com/privacy","privacy_policy_version":"2026-07-29","wording_id":"newsletter-v1","wording_sha256":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},"consent_granted":true,"contact":{"email":"synthetic-phase5@example.test","first_name":"Synthetic"},"destination_audience_id":"22222222-2222-4222-8222-222222222222","schema_version":"connect.subscription-source-event.v1","source":{"evidence_schema_version":"memoupdate.newsletter-consent-capture.v1","form_id":"synthetic-form","form_version":"1","page_origin":"https://my.lifeisshortdoitnow.com"},"source_event_id":"11111111-1111-4111-8111-111111111111"}],"properties":{"captured_at":{"format":"date-time","type":"string"},"consent":{"properties":{"privacy_policy_url":{"format":"uri","type":"string"},"privacy_policy_version":{"maxLength":160,"type":"string"},"wording_id":{"maxLength":160,"type":"string"},"wording_sha256":{"pattern":"^[a-f0-9]{64}$","type":"string"}},"required":["wording_id","wording_sha256","privacy_policy_url","privacy_policy_version"],"type":"object"},"consent_granted":{"const":true,"type":"boolean"},"contact":{"properties":{"email":{"format":"email","type":"string"},"first_name":{"maxLength":160,"type":"string"},"last_name":{"maxLength":160,"type":"string"},"locale":{"maxLength":40,"type":"string"}},"required":["email"],"type":"object"},"destination_audience_id":{"format":"uuid","type":"string"},"schema_version":{"const":"connect.subscription-source-event.v1","type":"string"},"source":{"properties":{"evidence_schema_version":{"const":"memoupdate.newsletter-consent-capture.v1","type":"string"},"form_id":{"maxLength":160,"type":"string"},"form_version":{"maxLength":160,"type":"string"},"page_origin":{"format":"uri","type":"string"},"popup_campaign_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}]},"popup_version":{"anyOf":[{"minimum":1,"type":"integer"},{"type":"null"}]}},"required":["form_id","form_version","page_origin","evidence_schema_version"],"type":"object"},"source_event_id":{"format":"uuid","type":"string"}},"required":["schema_version","source_event_id","destination_audience_id","contact","consent_granted","captured_at","consent","source"],"type":"object"},"SubscriptionSourceEventResponse":{"properties":{"audience_membership_active":{"type":"boolean"},"consent_event_id":{"format":"uuid","type":"string"},"correlation_id":{"type":"string"},"original_status":{"anyOf":[{"type":"string"},{"type":"null"}]},"reason_class":{"anyOf":[{"type":"string"},{"type":"null"}]},"receipt_id":{"format":"uuid","type":"string"},"schema_version":{"const":"connect.subscription-source-result.v1","type":"string"},"source_event_id":{"format":"uuid","type":"string"},"status":{"enum":["accepted","duplicate","review_required","suppressed"],"type":"string"}},"required":["schema_version","source_event_id","status","receipt_id","consent_event_id","audience_membership_active","reason_class","correlation_id"],"type":"object"},"SubscriptionSourceOriginsRequest":{"examples":[{"allowed_origins":["https://my.lifeisshortdoitnow.com"]}],"properties":{"allowed_origins":{"items":{"format":"uri","type":"string"},"type":"array"}},"required":["allowed_origins"],"type":"object"},"SubscriptionSourceResponse":{"properties":{"source":{"$ref":"#/components/schemas/SubscriptionSourceSummary"}},"required":["source"],"type":"object"},"SubscriptionSourceSummary":{"properties":{"allowed_audience_ids":{"items":{"format":"uuid","type":"string"},"type":"array"},"allowed_origins":{"items":{"type":"string"},"type":"array"},"allows_all_audiences":{"type":"boolean"},"display_name":{"type":"string"},"id":{"format":"uuid","type":"string"},"slug":{"type":"string"},"status":{"enum":["active","suspended","revoked"],"type":"string"}},"required":["id","slug","display_name","status","allows_all_audiences","allowed_audience_ids","allowed_origins"],"type":"object"},"SubscriptionSourcesResponse":{"properties":{"sources":{"items":{"$ref":"#/components/schemas/SubscriptionSourceSummary"},"type":"array"}},"required":["sources"],"type":"object"},"SuppressRequest":{"examples":[{"reason":"manual","scope":"workspace","source":"authorized_api"}],"properties":{"audience_id":{"type":"string"},"evidence":{"additionalProperties":true,"type":"object"},"reason":{"type":"string"},"scope":{"enum":["audience","workspace","platform"],"type":"string"},"source":{"type":"string"}},"required":["scope","reason"],"type":"object"},"SuppressResponse":{"properties":{"suppressed":{"type":"boolean"},"suppression_id":{"type":"string"}},"required":["suppressed","suppression_id"],"type":"object"},"SyntheticRehearsal":{"properties":{"claimed_count":{"anyOf":[{"type":"integer"},{"type":"null"}]},"cleanup_verified":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"completed_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}]},"created_at":{"format":"date-time","type":"string"},"duplicate_claim_count":{"anyOf":[{"type":"integer"},{"type":"null"}]},"elapsed_milliseconds":{"anyOf":[{"type":"integer"},{"type":"null"}]},"eligible_count":{"anyOf":[{"type":"integer"},{"type":"null"}]},"excluded_count":{"anyOf":[{"type":"integer"},{"type":"null"}]},"id":{"type":"string"},"provider_call_count":{"type":"integer"},"recipient_count":{"type":"integer"},"recovered_count":{"anyOf":[{"type":"integer"},{"type":"null"}]},"report":{"additionalProperties":true,"type":"object"},"report_checksum":{"anyOf":[{"type":"string"},{"type":"null"}]},"requested_by_gfavip_id":{"type":"string"},"state":{"type":"string"},"target_seconds":{"type":"integer"},"workspace_id":{"type":"string"}},"required":["id","workspace_id","state","recipient_count","target_seconds","elapsed_milliseconds","eligible_count","excluded_count","claimed_count","recovered_count","duplicate_claim_count","provider_call_count","cleanup_verified","report","report_checksum","requested_by_gfavip_id","created_at","completed_at"],"type":"object"},"SyntheticRehearsalDetailResponse":{"properties":{"run":{"$ref":"#/components/schemas/SyntheticRehearsal"}},"required":["run"],"type":"object"},"SyntheticRehearsalRequest":{"examples":[{"confirmation":"RUN 10000 SYNTHETIC REHEARSAL","idempotency_key":"synthetic-capacity-10000-0001","recipient_count":10000}],"properties":{"confirmation":{"type":"string"},"idempotency_key":{"maxLength":200,"minLength":12,"type":"string"},"recipient_count":{"maximum":10000,"minimum":100,"type":"integer"}},"required":["idempotency_key","confirmation"],"type":"object"},"SyntheticRehearsalResponse":{"properties":{"created":{"type":"boolean"},"run":{"$ref":"#/components/schemas/SyntheticRehearsal"}},"required":["created","run"],"type":"object"},"TestSend":{"properties":{"attempt_count":{"type":"integer"},"content_version_id":{"type":"string"},"id":{"type":"string"},"provider_message_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"recipient_email":{"type":"string"},"sender_identity_id":{"type":"string"},"state":{"type":"string"}},"required":["id","state","sender_identity_id","content_version_id","recipient_email","attempt_count","provider_message_id"],"type":"object"},"TestSendRequest":{"examples":[{"confirmation":"SEND TEST EMAIL","content_version_id":"content-version-id","recipient_email":"allowlisted@example.com","sender_identity_id":"sender-id"}],"properties":{"confirmation":{"const":"SEND TEST EMAIL","type":"string"},"content_version_id":{"type":"string"},"recipient_email":{"format":"email","type":"string"},"sender_identity_id":{"type":"string"}},"required":["sender_identity_id","content_version_id","recipient_email","confirmation"],"type":"object"},"TestSendResponse":{"properties":{"test_send":{"$ref":"#/components/schemas/TestSend"}},"required":["test_send"],"type":"object"},"User":{"properties":{"gfavip_user_id":{"type":"string"},"identity_type":{"enum":["human","agent"],"type":"string"},"platform_role":{"anyOf":[{"type":"string"},{"type":"null"}]},"username":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["gfavip_user_id","username","identity_type","platform_role"],"type":"object"},"WorkspaceActivationResponse":{"properties":{"workspace":{"properties":{"id":{"type":"string"},"production_sending_enabled":{"type":"boolean"}},"required":["id","production_sending_enabled"],"type":"object"}},"required":["workspace"],"type":"object"},"WorkspaceAudiencesResponse":{"properties":{"audiences":{"items":{"properties":{"id":{"format":"uuid","type":"string"},"is_archived":{"type":"boolean"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug","is_archived"],"type":"object"},"type":"array"}},"required":["audiences"],"type":"object"},"WorkspaceListItem":{"properties":{"is_archived":{"type":"boolean"},"name":{"type":"string"},"organization":{"type":"string"},"production_sending_enabled":{"type":"boolean"},"role":{"type":"string"},"workspace":{"type":"string"}},"required":["organization","workspace","name","role","is_archived","production_sending_enabled"],"type":"object"},"WorkspaceResponse":{"properties":{"capabilities":{"items":{"type":"string"},"type":"array"},"is_archived":{"type":"boolean"},"name":{"type":"string"},"organization":{"type":"string"},"production_sending_enabled":{"type":"boolean"},"role":{"type":"string"},"workspace":{"type":"string"}},"required":["organization","workspace","name","role","capabilities","is_archived","production_sending_enabled"],"type":"object"},"WorkspacesResponse":{"properties":{"workspaces":{"items":{"$ref":"#/components/schemas/WorkspaceListItem"},"type":"array"}},"required":["workspaces"],"type":"object"}},"securitySchemes":{"bearerAuth":{"description":"Wallet-issued `gfavip-session-*` token. Never send a PowerLobster API key to Connect.","scheme":"bearer","type":"http"},"serviceApiKey":{"description":"Shared server-to-server credential for GFA Console (see GFA_SERVICE_API_KEY). Requires a second header, `X-User-ID`, naming the GFAVIP user to act for; that user must already exist here as an Operator, provisioned via a session login or a Wallet bearer call. Limited to the `edit_content` capability -- every other capability, including every sending-related route, refuses a service-authenticated caller regardless of the acting user's own role.","in":"header","name":"X-API-Key","type":"apiKey"},"sessionCookie":{"description":"Human browser session. Mutating API requests also require `X-CSRF-Token`.","in":"cookie","name":"session","type":"apiKey"},"sourceCredential":{"description":"Two ways in, both a bearer token in this header. Either a hashed, revocable static credential for one registered subscription source, which carries no scope of its own, so whatever that source is configured to allow is the only limit on what it can reach; or a Wallet-issued grant token whose scope names this source and includes the permission the operation requires -- `events.write` to ingest, `audiences.read` to list audiences.","scheme":"bearer","type":"http"}}},"info":{"description":"Implemented production API for governed contacts, consent, authoring, protected CSV imports, versioned automation authoring, a synthetic-only durable automation runtime foundation, sender readiness, delivery controls, and operational rehearsals. Production automation enrollment, execution, and external actions remain unavailable.","title":"HeliumRises Connect API","version":"2026-07-28"},"openapi":"3.1.0","paths":{"/api/v1/me":{"get":{"description":"The live response contains `user`, `auth_method`, `csrf_token`, and `workspaces`. There is no top-level `memberships` field.","operationId":"getMe","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Get validated identity and local memberships","tags":["Identity"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"authenticated","x-safe":true,"x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}":{"get":{"description":"","operationId":"getWorkspace","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Get workspace role, capabilities, and send state","tags":["Identity"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/activate-sending":{"post":{"description":"Requires `ACTIVATE PRODUCTION SENDING`, a ready sender, and all global activation gates.","operationId":"activateWorkspaceSending","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductionActivationRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceActivationResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Activate workspace production sending","tags":["Sender readiness"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":true,"x-required-capability":"manage_senders","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/audiences":{"get":{"description":"Every audience in the workspace, for a caller rendering a picker. Archived audiences are included and flagged rather than omitted: a caller needs to know one exists and cannot be chosen, since its absence would otherwise read as a missing audience.","operationId":"listWorkspaceAudiences","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceAudiencesResponse"}}},"description":"Audiences in this workspace","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Caller lacks the view capability here. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"List the workspace's audiences","tags":["Subscription sources"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"read-only"},"post":{"description":"","operationId":"createAudience","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceCreateRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceCreateResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"409":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Uniqueness or source-identity conflict. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Create an audience","tags":["Audiences"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"upsert_contacts","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/audiences/{audience_id}":{"get":{"description":"","operationId":"getAudience","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable audience id.","in":"path","name":"audience_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Inspect an audience","tags":["Audiences"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/audiences/{audience_id}/archive":{"post":{"description":"","operationId":"archiveAudience","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable audience id.","in":"path","name":"audience_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArchiveResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Archive an audience","tags":["Audiences"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"upsert_contacts","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/audiences/{audience_id}/subscribe":{"post":{"description":"Refuses with 422 when an unresolved Suppression blocks the contact -- platform-wide, scoped to this workspace, or scoped to this audience -- naming the blocking scope and reason in the error. There is no parameter to override this. Resolve the suppression first via POST /suppressions/{suppression_id}/resolve (resolve_suppressions capability), then call subscribe again.","operationId":"subscribeContact","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable audience id.","in":"path","name":"audience_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceSubscribeRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceSubscribeResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Record consent and activate audience membership","tags":["Consent and safety"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"upsert_contacts","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/audiences/{audience_id}/unsubscribe":{"post":{"description":"","operationId":"unsubscribeContact","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable audience id.","in":"path","name":"audience_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceUnsubscribeRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceUnsubscribeResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Unsubscribe a contact from an audience","tags":["Consent and safety"],"x-idempotency":"Safe to repeat; the resulting audience permission remains unsubscribed.","x-platform-and-workspace-owner-required":false,"x-required-capability":"upsert_contacts","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/automation-enrollments/{enrollment_id}":{"get":{"description":"","operationId":"getAutomationEnrollment","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable enrollment id.","in":"path","name":"enrollment_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationEnrollmentResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Inspect a synthetic enrollment timeline","tags":["Automations"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"read-only-runtime-observability"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/automation-enrollments/{enrollment_id}/{action}":{"post":{"description":"Hard-blocked while the Phase 5D runtime gate is closed.","operationId":"controlSyntheticAutomationEnrollment","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable enrollment id.","in":"path","name":"enrollment_id","required":true,"schema":{"type":"string"}},{"description":"Stable action.","in":"path","name":"action","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationEnrollmentControlRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationEnrollmentResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"409":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Uniqueness or source-identity conflict. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Pause, resume, cancel, or replay synthetic runtime state","tags":["Automations"],"x-idempotency":"State-machine constrained; invalid repeats return 409.","x-platform-and-workspace-owner-required":false,"x-required-capability":"pause_delivery","x-safety-class":"synthetic-only-runtime-control"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/automations":{"get":{"description":"Returns workspace-local immutable authoring state. Phase 5B has no enrollment, execution, activation, provider, or webhook path.","operationId":"listAutomations","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationListResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"List non-executable automation definitions","tags":["Automations"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"read-only-authoring"},"post":{"description":"Validates graph structure and workspace dependencies. Makes zero provider or webhook calls and creates no enrollment.","operationId":"createAutomation","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationCreateRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Create a validated automation draft and immutable version","tags":["Automations"],"x-idempotency":"Not idempotent. Automation slug uniqueness prevents duplicate workspace definitions.","x-platform-and-workspace-owner-required":false,"x-required-capability":"edit_automations","x-safety-class":"database-only-authoring"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/automations/{automation_id}":{"get":{"description":"","operationId":"getAutomation","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable automation id.","in":"path","name":"automation_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Inspect an automation and immutable version history","tags":["Automations"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"read-only-authoring"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/automations/{automation_id}/archive":{"post":{"description":"","operationId":"archiveAutomation","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable automation id.","in":"path","name":"automation_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Archive an automation authoring definition","tags":["Automations"],"x-idempotency":"Safe to repeat; the authoring definition remains archived.","x-platform-and-workspace-owner-required":false,"x-required-capability":"edit_automations","x-safety-class":"database-only-authoring"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/automations/{automation_id}/enrollments":{"get":{"description":"Production currently returns an empty collection.","operationId":"listAutomationEnrollments","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable automation id.","in":"path","name":"automation_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationEnrollmentListResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"List synthetic-only durable automation enrollments","tags":["Automations"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"read-only-runtime-observability"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/automations/{automation_id}/ready-for-review":{"post":{"description":"Records an authoring milestone only. It cannot enroll contacts, schedule steps, send email, call a webhook, or open a gate.","operationId":"markAutomationReadyForReview","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable automation id.","in":"path","name":"automation_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationReviewReadyRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Mark the current checksum-bound version ready for review","tags":["Automations"],"x-idempotency":"Safe to repeat for the same current version and checksum. This is not activation or approval to execute.","x-platform-and-workspace-owner-required":false,"x-required-capability":"edit_automations","x-safety-class":"database-only-review-state"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/automations/{automation_id}/restore":{"post":{"description":"Restores authoring only and cannot activate execution.","operationId":"restoreAutomation","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable automation id.","in":"path","name":"automation_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Restore an archived definition as a draft","tags":["Automations"],"x-idempotency":"Accepted only while archived; a repeated request after restore returns 422.","x-platform-and-workspace-owner-required":false,"x-required-capability":"edit_automations","x-safety-class":"database-only-authoring"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/automations/{automation_id}/versions":{"post":{"description":"Resets review-ready state to draft. Does not change or migrate historical versions.","operationId":"createAutomationVersion","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable automation id.","in":"path","name":"automation_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationVersionRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Append a validated immutable automation version","tags":["Automations"],"x-idempotency":"Not idempotent. Each accepted request appends a new immutable version.","x-platform-and-workspace-owner-required":false,"x-required-capability":"edit_automations","x-safety-class":"database-only-authoring"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/automations/{automation_id}/versions/{version_id}":{"get":{"description":"","operationId":"getAutomationVersion","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable automation id.","in":"path","name":"automation_id","required":true,"schema":{"type":"string"}},{"description":"Stable version id.","in":"path","name":"version_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Inspect one immutable automation version","tags":["Automations"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"read-only-authoring"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/automations/{automation_id}/versions/{version_id}/synthetic-enrollments":{"post":{"description":"Hard-blocked in production. Accepts only archived synthetic workspaces and `.invalid` contacts bound to a rehearsal ID.","operationId":"createSyntheticAutomationEnrollment","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable automation id.","in":"path","name":"automation_id","required":true,"schema":{"type":"string"}},{"description":"Stable version id.","in":"path","name":"version_id","required":true,"schema":{"type":"string"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":200,"minLength":12,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationSyntheticEnrollmentRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationEnrollmentResponse"}}},"description":"Successful idempotent replay or update","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationEnrollmentResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"409":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Uniqueness or source-identity conflict. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Create an idempotent non-production synthetic enrollment","tags":["Automations"],"x-idempotency":"Required Idempotency-Key; replay returns the original row.","x-platform-and-workspace-owner-required":false,"x-required-capability":"edit_automations","x-safety-class":"synthetic-only-runtime"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/campaign-drafts":{"post":{"description":"Database-only draft creation. It schedules and sends nothing.","operationId":"createCampaignDraft","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignDraftRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]},{"serviceApiKey":[]}],"summary":"Create a campaign draft","tags":["Campaigns"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"edit_content","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/campaign-drafts/{campaign_id}/schedule":{"post":{"description":"Fails closed unless every global, workspace, provider, domain, sender, content, and production-sending gate is open.","operationId":"scheduleCampaign","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable campaign id.","in":"path","name":"campaign_id","required":true,"schema":{"type":"string"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":200,"minLength":12,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignRunResponse"}}},"description":"Successful idempotent replay or update","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignRunResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Create an immutable scheduled campaign run","tags":["Campaigns"],"x-idempotency":"Required `Idempotency-Key`; a replay for the same campaign returns the original run with 200.","x-platform-and-workspace-owner-required":false,"x-required-capability":"schedule_campaign","x-safety-class":"production-delivery-path"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/campaign-drafts/{campaign_id}/versions":{"post":{"description":"","operationId":"createCampaignDraftVersion","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable campaign id.","in":"path","name":"campaign_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignDraftRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]},{"serviceApiKey":[]}],"summary":"Append an immutable campaign draft version","tags":["Campaigns"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"edit_content","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/campaign-runs/{run_id}":{"get":{"description":"","operationId":"getCampaignRun","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable run id.","in":"path","name":"run_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignRunResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Inspect a campaign run","tags":["Campaigns"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/campaign-runs/{run_id}/report":{"get":{"description":"","operationId":"getCampaignReport","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable run id.","in":"path","name":"run_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignReportResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Inspect per-recipient delivery outcomes and reconciled reporting","tags":["Campaigns"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/campaign-runs/{run_id}/unschedule":{"post":{"description":"","operationId":"unscheduleCampaign","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable run id.","in":"path","name":"run_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignRunResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Cancel a still-pending schedule","tags":["Campaigns"],"x-idempotency":"Not replay-safe after the run leaves `scheduled`; later calls return 422.","x-platform-and-workspace-owner-required":false,"x-required-capability":"schedule_campaign","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/campaign-runs/{run_id}/{action}":{"post":{"description":"","operationId":"controlCampaignRun","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable run id.","in":"path","name":"run_id","required":true,"schema":{"type":"string"}},{"in":"path","name":"action","required":true,"schema":{"enum":["pause","resume","cancel"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignRunResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Pause, resume, or cancel a campaign run","tags":["Campaigns"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"pause_delivery","x-safety-class":"delivery-control"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/campaign-webhook":{"post":{"description":"Sets or clears the URL Console is notified at when a campaign is scheduled, completes, is cancelled, or fails, and the secret sent as a plaintext X-Webhook-Secret header on every delivery for the receiver to compare. A key absent from the body leaves that field unchanged. A workspace with no URL configured emits nothing. The secret is write-only and never appears in the response.","operationId":"updateCampaignWebhook","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignWebhookRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignWebhookResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Configure where campaign lifecycle events are POSTed","tags":["Campaigns"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"manage_senders","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/contact-field-definitions":{"post":{"description":"","operationId":"createContactFieldDefinition","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactFieldDefinitionRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactFieldDefinitionResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Create the next typed custom-field definition","tags":["Contacts"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"upsert_contacts","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/contacts/lookup":{"get":{"description":"","operationId":"lookupContact","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"in":"query","name":"email","required":true,"schema":{"format":"email","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Look up a contact by normalized email","tags":["Contacts"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/contacts/upsert":{"post":{"description":"","operationId":"upsertContact","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactUpsertRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactUpsertResponse"}}},"description":"Successful idempotent replay or update","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactUpsertResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"409":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Uniqueness or source-identity conflict. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Create or update a contact","tags":["Contacts"],"x-idempotency":"Idempotent by normalized email; source identity conflicts return 409.","x-platform-and-workspace-owner-required":false,"x-required-capability":"upsert_contacts","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/contacts/{contact_id}/eligibility/{audience_id}":{"get":{"description":"Read-only evaluation. It never contacts Mailgun or a recipient.","operationId":"checkEligibility","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable contact id.","in":"path","name":"contact_id","required":true,"schema":{"type":"string"}},{"description":"Stable audience id.","in":"path","name":"audience_id","required":true,"schema":{"type":"string"}},{"in":"query","name":"message_idempotency_key","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EligibilityResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Evaluate centralized send eligibility","tags":["Consent and safety"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/contacts/{contact_id}/preference-token":{"post":{"description":"","operationId":"issuePreferenceToken","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable contact id.","in":"path","name":"contact_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreferenceTokenRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreferenceTokenResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Issue scoped preference and one-click URLs","tags":["Consent and safety"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"upsert_contacts","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/contacts/{contact_id}/suppress":{"post":{"description":"","operationId":"suppressContact","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable contact id.","in":"path","name":"contact_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Create a safety suppression","tags":["Consent and safety"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"resolve_suppressions","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/email-templates":{"post":{"description":"","operationId":"createEmailTemplate","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplateRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplateResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]},{"serviceApiKey":[]}],"summary":"Create an email-template container","tags":["Content"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"edit_content","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/email-templates/{template_id}/archive":{"post":{"description":"Shelves the template container. Send `{\"archived\": false}` to restore it; an empty body archives. Content versions are untouched, and a campaign already referencing one keeps working. The slug stays reserved either way, since slugs are unique per workspace whether or not the template is archived.","operationId":"archiveEmailTemplate","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable template id.","in":"path","name":"template_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplateArchiveRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplateArchiveResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]},{"serviceApiKey":[]}],"summary":"Archive or restore an email template","tags":["Content"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"edit_content","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/email-templates/{template_id}/versions":{"post":{"description":"Database-only authoring. It sends no email. The submitted HTML is sanitized against an allowlist before it is stored, and only the sanitized copy is ever sent. Check `validation.stripped` on the response: it lists tags, attributes, and CSS properties the sanitizer removed. Non-empty lists mean the stored email no longer looks like what was submitted. /skill.md documents the allowlist and the house email structure.","operationId":"createContentVersion","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable template id.","in":"path","name":"template_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentVersionRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentVersionResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]},{"serviceApiKey":[]}],"summary":"Create an immutable sanitized content version","tags":["Content"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"edit_content","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/imports/csv":{"get":{"description":"","operationId":"listCsvImports","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsvImportListResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"List protected CSV imports","tags":["Imports"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"read-only"},"post":{"description":"","operationId":"uploadCsvImport","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"requestBody":{"content":{"multipart/form-data":{"schema":{"properties":{"audience_id":{"type":"string"},"file":{"description":"UTF-8 CSV protected immediately after upload.","format":"binary","type":"string"},"source_label":{"maxLength":160,"type":"string"}},"required":["file","audience_id","source_label"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsvImportResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Upload a protected CSV","tags":["Imports"],"x-idempotency":"Not idempotent. The response job ID and file checksum identify the durable upload; do not retry after receiving 201.","x-platform-and-workspace-owner-required":false,"x-required-capability":"upsert_contacts","x-safety-class":"encrypted-upload-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/imports/csv-mapping-profiles":{"get":{"description":"","operationId":"listCsvImportMappingProfiles","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsvImportMappingProfileListResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"List reusable CSV mapping profiles","tags":["Imports"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"read-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/imports/csv/{job_id}":{"get":{"description":"","operationId":"getCsvImport","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable job id.","in":"path","name":"job_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsvImportResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Inspect a protected CSV import","tags":["Imports"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"read-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/imports/csv/{job_id}/approve":{"post":{"description":"","operationId":"approveCsvImport","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable job id.","in":"path","name":"job_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsvImportApprovalRequest"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsvImportResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Approve a checksum-bound import apply","tags":["Imports"],"x-idempotency":"Approval is checksum-bound and accepted once. Apply uses a per-row idempotency ledger.","x-platform-and-workspace-owner-required":false,"x-required-capability":"approve_imports","x-safety-class":"database-import-queue"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/imports/csv/{job_id}/cancel":{"post":{"description":"","operationId":"cancelCsvImport","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable job id.","in":"path","name":"job_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsvImportResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Cancel an import and destroy its payload","tags":["Imports"],"x-idempotency":"Terminal cleanup operation. A cancelled or purged payload cannot be restored.","x-platform-and-workspace-owner-required":false,"x-required-capability":"upsert_contacts","x-safety-class":"destructive-payload-cleanup"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/imports/csv/{job_id}/mapping":{"patch":{"description":"","operationId":"configureCsvImport","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable job id.","in":"path","name":"job_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsvImportMappingRequest"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsvImportResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Configure mapping and queue a zero-write dry run","tags":["Imports"],"x-idempotency":"Repeatable before approval. Reconfiguration invalidates any prior report and approval.","x-platform-and-workspace-owner-required":false,"x-required-capability":"upsert_contacts","x-safety-class":"zero-write-analysis-queue"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/imports/csv/{job_id}/retry":{"post":{"description":"","operationId":"retryCsvImport","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable job id.","in":"path","name":"job_id","required":true,"schema":{"type":"string"}}],"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsvImportResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Retry a failed import safely","tags":["Imports"],"x-idempotency":"Only failed jobs are accepted. A still-valid checksum-bound approval retries apply; otherwise the job returns to dry run.","x-platform-and-workspace-owner-required":false,"x-required-capability":"upsert_contacts","x-safety-class":"idempotent-recovery-queue"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/operations/preflight":{"get":{"description":"","operationId":"getLatestPreflight","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreflightResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Get the latest launch preflight","tags":["Operations"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"database-only"},"post":{"description":"May perform readiness inspection but sends no email and opens no gates.","operationId":"runPreflight","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreflightResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Run the fail-closed launch preflight","tags":["Operations"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"manage_senders","x-safety-class":"read-only-checks-with-retained-report"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/operations/synthetic-rehearsals":{"post":{"description":"Uses no subscriber data, makes zero provider calls, sends no email, and rolls back synthetic operational rows.","operationId":"startSyntheticRehearsal","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyntheticRehearsalRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyntheticRehearsalResponse"}}},"description":"Successful idempotent replay or update","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyntheticRehearsalResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Queue an isolated synthetic capacity rehearsal","tags":["Operations"],"x-idempotency":"Required body `idempotency_key`; a replay returns the original run with 200.","x-platform-and-workspace-owner-required":true,"x-required-capability":"manage_senders","x-safety-class":"synthetic-database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/operations/synthetic-rehearsals/{run_id}":{"get":{"description":"","operationId":"getSyntheticRehearsal","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable run id.","in":"path","name":"run_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyntheticRehearsalDetailResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Inspect a synthetic capacity rehearsal","tags":["Operations"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/provider-connections":{"post":{"description":"","operationId":"createProviderConnection","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderConnectionRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderConnectionResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Create a secret-reference-only Mailgun connection","tags":["Sender readiness"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"manage_senders","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/provider-connections/{connection_id}/activate":{"post":{"description":"Requires the exact confirmation `ENABLE TEST CONNECTION`. This does not enable production sending.","operationId":"activateProviderConnection","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable connection id.","in":"path","name":"connection_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderActivationRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderConnectionResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Enable a verified connection for test activity","tags":["Sender readiness"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"manage_senders","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/provider-connections/{connection_id}/check":{"post":{"description":"Contacts Mailgun for an account-level check but sends no email.","operationId":"checkProviderConnection","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable connection id.","in":"path","name":"connection_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderConnectionResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Test the Mailgun connection","tags":["Sender readiness"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"manage_senders","x-safety-class":"external-read-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/provider-events/{event_id}/replay":{"post":{"description":"","operationId":"replayProviderEvent","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable event id.","in":"path","name":"event_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderEventReplayResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Replay a stored verified provider event","tags":["Operations"],"x-idempotency":"Provider-event processing is deduplicated by the stored provider event.","x-platform-and-workspace-owner-required":false,"x-required-capability":"pause_delivery","x-safety-class":"database-only-event-reprocessing"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/rehearsals":{"post":{"description":"Queues one gated test email and observes signed Mailgun events. It is not a marketing send.","operationId":"startControlledRehearsal","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":200,"minLength":12,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RehearsalRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RehearsalResponse"}}},"description":"Successful idempotent replay or update","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RehearsalResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Start a controlled provider-event rehearsal","tags":["Delivery safety"],"x-idempotency":"Required `Idempotency-Key`; a replay returns the original rehearsal with 200.","x-platform-and-workspace-owner-required":false,"x-required-capability":"send_test","x-safety-class":"may-contact-mailgun-and-one-allowlisted-recipient"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/rehearsals/{rehearsal_id}":{"get":{"description":"","operationId":"getControlledRehearsal","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable rehearsal id.","in":"path","name":"rehearsal_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RehearsalResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Inspect controlled rehearsal reconciliation","tags":["Delivery safety"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"view","x-safe":true,"x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/sender-identities":{"post":{"description":"","operationId":"createSenderIdentity","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderIdentityRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderIdentityResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Create a disabled sender identity","tags":["Sender readiness"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"manage_senders","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/sender-identities/{sender_id}/activate":{"post":{"description":"Requires `ACTIVATE PRODUCTION SENDING` and closed-by-default global activation gates.","operationId":"activateSenderIdentity","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable sender id.","in":"path","name":"sender_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductionActivationRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderActivationResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Activate a sender behind production gates","tags":["Sender readiness"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":true,"x-required-capability":"manage_senders","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/sending-domains":{"post":{"description":"","operationId":"createSendingDomain","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendingDomainRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendingDomainResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Create a sender-domain readiness record","tags":["Sender readiness"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"manage_senders","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/sending-domains/{domain_id}/provider":{"post":{"description":"","operationId":"configureDomainProvider","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable domain id.","in":"path","name":"domain_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainProviderRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendingDomainResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Associate a Mailgun connection and DKIM selector","tags":["Sender readiness"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"manage_senders","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/sending-domains/{domain_id}/readiness":{"post":{"description":"","operationId":"updateDomainReadiness","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable domain id.","in":"path","name":"domain_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendingDomainReadinessRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendingDomainResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Update manually recorded domain readiness","tags":["Sender readiness"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"manage_senders","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/sending-domains/{domain_id}/verify":{"post":{"description":"Performs DNS lookups and Mailgun status reads. It sends no email.","operationId":"verifySendingDomain","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable domain id.","in":"path","name":"domain_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainVerifyResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Run live DNS and Mailgun domain verification","tags":["Sender readiness"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"manage_senders","x-safety-class":"external-read-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/subscription-sources":{"get":{"description":"For a caller attaching to an existing source rather than creating a near-duplicate. Each entry carries the source's id, which is what a grant scope names -- never its slug, which is unique only within one workspace. No credential is ever included.","operationId":"listSubscriptionSources","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionSourcesResponse"}}},"description":"Sources in this workspace","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Caller lacks manage_subscription_sources here. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"List the workspace's subscription sources","tags":["Subscription sources"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"manage_subscription_sources","x-safe":true,"x-safety-class":"read-only"},"post":{"description":"Creates the source and returns it, including its id, so the caller can build a grant scope naming it. Mints no credential and none is needed: a source created this way is expected to authenticate with a Wallet grant scoped to that id. Issuing, rotating and revoking a static credential remain console-only, because that flow shows a secret exactly once. Choose how the source allows audiences: `allowed_audience_ids` is required, naming at least one live audience in this workspace, unless `allows_all_audiences` is true; with the flag true it must be absent, null or empty, and a non-empty list beside it is a `422` rather than a resolution of the two.","operationId":"createSubscriptionSource","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionSourceCreateRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionSourceResponse"}}},"description":"The created source","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"400":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"JSON object required. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Caller lacks manage_subscription_sources, or the workspace is archived. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"409":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"A subscription source with that slug already exists in this workspace. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Slug, display name, audiences or origins invalid. An audience outside this workspace is refused identically to an unknown one. A non-empty allowed_audience_ids sent together with a true allows_all_audiences is refused rather than resolved, and so is an absent or empty allowed_audience_ids without the flag. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Create a subscription source","tags":["Subscription sources"],"x-idempotency":"Not idempotent. Creating the same slug twice returns 409 rather than the existing source.","x-platform-and-workspace-owner-required":false,"x-required-capability":"manage_subscription_sources","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/subscription-sources/{source_slug}/audiences":{"get":{"description":"Read-only companion to the ingest route, for a caller building an audience picker. Returns exactly the audiences this source may write to, minus archived ones -- its audience allowlist, or every live audience in its own workspace when it was created with `allows_all_audiences` -- so a rendered picker cannot offer a choice ingestion would refuse. A static source credential carries no scope and reaches this route on whatever the source itself allows. A grant token must carry `audiences.read` in its scope; a grant scoped only to `events.write` is refused here, so a caller needing both lists both.","operationId":"listSubscriptionSourceAudiences","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Registered subscription source slug.","in":"path","name":"source_slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionSourceAudiencesResponse"}}},"description":"Allowed, unarchived audiences for this source","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Invalid or expired source credential. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Source revoked, suspended, or route mismatch. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"429":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Rate limit exceeded for this subscription source. Counted per source over a fixed one-minute window and applied before the credential is checked, so an invalid credential is counted too.. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"sourceCredential":[]}],"summary":"List the audiences this source may write to","tags":["Subscription sources"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-required-capability":"active subscription-source credential, or a grant token whose scope names this source and includes audiences.read","x-safe":true,"x-safety-class":"read-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/subscription-sources/{source_slug}/events":{"post":{"description":"Source-only ingestion for MemoUpdate. The credential is fixed to one workspace, one source, that source's origin allowlist, and the audiences that source allows -- either its exact audience allowlist or, for a source created with `allows_all_audiences`, any live audience in its own workspace. This operation cannot schedule or send.","operationId":"ingestSubscriptionSourceEvent","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Registered subscription source slug.","in":"path","name":"source_slug","required":true,"schema":{"type":"string"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":200,"minLength":12,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionSourceEventRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionSourceEventResponse"}}},"description":"Exact idempotent replay","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionSourceEventResponse"}}},"description":"Consent accepted and audience membership active","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionSourceEventResponse"}}},"description":"Consent recorded but suppression or review prevents membership","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Invalid or expired source credential. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Source revoked, suspended, or route mismatch. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"409":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Idempotency key payload conflict. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Invalid evidence, audience, origin, or consent. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"429":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Rate limit exceeded for this subscription source. The limit is counted per source over a fixed one-minute window and applies before the credential is checked, so an invalid credential is counted too. `Retry-After` carries the window length in seconds.. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Transient ingestion failure. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"sourceCredential":[]}],"summary":"Record explicit consent from an approved source","tags":["Subscription sources"],"x-idempotency":"Required Idempotency-Key. Exact replay returns the original receipt as duplicate; a changed payload returns 409.","x-required-capability":"active subscription-source credential, or a grant token whose scope names this source and includes events.write","x-safety-class":"consent-ingestion-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/subscription-sources/{source_slug}/origins":{"patch":{"description":"Takes the complete list, never a delta. This set decides whether a live submission is accepted, so a partial apply would surface as signups quietly not arriving rather than as an error. The slug cannot be changed here: it is in the URL every live form posts to.","operationId":"replaceSubscriptionSourceOrigins","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Registered subscription source slug.","in":"path","name":"source_slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionSourceOriginsRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionSourceResponse"}}},"description":"The updated source","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"400":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"JSON object required. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Caller lacks manage_subscription_sources, or the workspace is archived. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"No such source in this workspace. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Every origin must be a plain https origin. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Replace a source's allowed origins","tags":["Subscription sources"],"x-idempotency":"Idempotent: replaces the complete origin list, so repeating the same request leaves the source in the same state.","x-platform-and-workspace-owner-required":false,"x-required-capability":"manage_subscription_sources","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/suppressions/{suppression_id}/resolve":{"post":{"description":"Platform-scope safety suppressions also require a platform owner or administrator.","operationId":"resolveSuppression","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"description":"Stable suppression id.","in":"path","name":"suppression_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveSuppressionRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolvedResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Resolve an eligible suppression","tags":["Consent and safety"],"x-idempotency":"Not guaranteed idempotent; check operation-specific retry behavior.","x-platform-and-workspace-owner-required":false,"x-required-capability":"resolve_suppressions","x-safety-class":"database-only"}},"/api/v1/organizations/{organization_slug}/workspaces/{workspace_slug}/test-sends":{"post":{"description":"Requires `SEND TEST EMAIL`, an allowlisted recipient, verified domain, active provider, and test-send configuration gate.","operationId":"requestTestSend","parameters":[{"$ref":"#/components/parameters/OrganizationSlug"},{"$ref":"#/components/parameters/WorkspaceSlug"},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":200,"minLength":12,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestSendRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestSendResponse"}}},"description":"Successful idempotent replay or update","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestSendResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"403":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authenticated but not authorized. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Resource or unauthorized workspace not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"422":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Request failed validation or a safety gate. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"Queue a tightly gated allowlisted test email","tags":["Delivery safety"],"x-idempotency":"Required `Idempotency-Key`; a replay returns the original request with 200.","x-platform-and-workspace-owner-required":false,"x-required-capability":"send_test","x-safety-class":"may-contact-mailgun-and-one-allowlisted-recipient"}},"/api/v1/workspaces":{"get":{"description":"","operationId":"listWorkspaces","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspacesResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Authentication required or Wallet token invalid. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Wallet identity validation unavailable. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"summary":"List locally assigned workspaces","tags":["Identity"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-platform-and-workspace-owner-required":false,"x-required-capability":"authenticated","x-safe":true,"x-safety-class":"database-only"}},"/healthz":{"get":{"operationId":"health","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[],"summary":"Process health","tags":["Operations"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-safe":true}},"/preferences/one-click/{token}":{"post":{"description":"A validly signed token is honoured however old it is, so a mail client's own unsubscribe button keeps working on an old message. Aged use is recorded on the audit event as `link_expired`. Forged, tampered, and foreign-key tokens are still refused with 400.","operationId":"oneClickUnsubscribe","parameters":[{"in":"path","name":"token","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"properties":{"List-Unsubscribe":{"const":"One-Click","type":"string"}},"required":["List-Unsubscribe"],"type":"object"}}},"required":true},"responses":{"204":{"description":"Unsubscribed; no response body","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"400":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Invalid RFC 8058 body, preference token, or purpose. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Contact or audience not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[],"summary":"Apply an RFC 8058 one-click unsubscribe","tags":["Consent and safety"],"x-idempotency":"Safe to repeat; unsubscribe state remains restrictive.","x-required-capability":"valid signed preference token","x-safety-class":"suppression-increasing-public-action"}},"/preferences/{token}":{"post":{"description":"A validly signed token is honoured however old it is. `PREFERENCE_TOKEN_MAX_AGE_SECONDS` decides when the hosted page tells the reader the link came from an older email, not when the link stops working: refusing an aged unsubscribe leaves the reader with no way out but a spam report. Aged use is recorded on the audit event as `link_expired`. Forged, tampered, and foreign-key tokens are still refused with 400.","operationId":"submitPreference","parameters":[{"in":"path","name":"token","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreferenceUnsubscribeResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"400":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Invalid preference token or purpose. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Contact or audience not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[],"summary":"Apply a signed preference unsubscribe","tags":["Consent and safety"],"x-idempotency":"Safe to repeat; unsubscribe state remains restrictive.","x-required-capability":"valid signed preference token","x-safety-class":"suppression-increasing-public-action"}},"/readyz":{"get":{"operationId":"readiness","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadinessResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadinessResponse"}}},"description":"Database unavailable","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[],"summary":"Database readiness","tags":["Operations"],"x-idempotency":"Safe and idempotent read-only operation; repeating it does not change server state.","x-idempotent":true,"x-safe":true}},"/webhooks/mailgun/{connection_id}":{"post":{"description":"Provider callback. Accepts JSON or Mailgun form fields whose `event-data` and `signature` values are JSON strings.","operationId":"receiveMailgunWebhook","parameters":[{"in":"path","name":"connection_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailgunWebhookEnvelope"}},"application/x-www-form-urlencoded":{"schema":{"properties":{"event-data":{"description":"JSON-encoded event data.","type":"string"},"signature":{"description":"JSON-encoded signature data.","type":"string"}},"required":["event-data","signature"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailgunWebhookResponse"}}},"description":"Successful response","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"400":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Invalid envelope, event, or unsupported event type. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"401":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Invalid or unavailable signing key. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Provider connection not found. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}},"429":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Rate limit exceeded for this provider connection. Counted per connection over a fixed one-minute window, ahead of signature verification, so one connection's burst cannot refuse another's. `Retry-After` carries the window length in seconds.. The current API returns Flask's standard `text/html` error body; use the HTTP status and `X-Correlation-ID` for handling.","headers":{"X-Correlation-ID":{"$ref":"#/components/headers/CorrelationId"}}}},"security":[],"summary":"Receive and deduplicate a signed Mailgun event","tags":["Operations"],"x-idempotency":"Deduplicated by provider connection and Mailgun event ID.","x-required-capability":"valid Mailgun webhook signature","x-safety-class":"signed-provider-event-processing"}}},"servers":[{"url":"https://connect.heliumrises.com"}],"tags":[{"name":"Identity"},{"name":"Contacts"},{"name":"Audiences"},{"name":"Imports"},{"name":"Consent and safety"},{"name":"Sender readiness"},{"name":"Content"},{"name":"Campaigns"},{"name":"Automations"},{"name":"Delivery safety"},{"name":"Operations"},{"name":"Subscription sources"}]}
